使用yield return返回从基类型继承的对象
我有一个名为Media
的bas类,其中有两个继承自它的类,Photo
和Video
。我正在尝试为媒体基类创建一个集合以容纳这些照片和视频对象。所以,我创建了一个MediaList
类,如下所示:使用yield return返回从基类型继承的对象
public class MediaList: ICollection<Media>
{
private readonly XElement _mediaElement;
public MediaList(XElement mediaElement)
{
_mediaElement = mediaElement;
}
public IEnumerator<Media> GetEnumerator()
{
foreach (XElement element in _mediaElement.Elements())
{
Media media;
switch (element.Name.LocalName)
{
case "video":
media = new Video(element);
break;
case "photo":
media = new Photo(element);
break;
default:
media = null;
break;
}
yield return media;
}
}
//Rest of ICollection Implementation
}
当我遍历列表中我得到以下异常:
值“Tool.Photo”的类型是不是“Tool.Video”,不能用于这个通用集合。
如果我返回Media
对象,为什么它抛出异常?有没有更好的方法来解决这个问题?
你的错误是在其他地方。只要Video和Photo从媒体继承,你所写的就没有问题。也许你试图把它错误地放在别的地方。
经过挖掘,你是对的,我的问题在别处。问题在哪里?叹息回到步进代码:-) – Geoff 2009-10-29 14:00:00
不应与收益率回报的方法输入返回IEnumerable<Media>
,不IEnumerator<Media>
?
但更基本,这种模式给我留下难闻的气味。每次你对这个“集”使用的foreach,您将创建(实例)在_mediaElement.Elements()
列表中的每个Photo
或Video
对象的新实例。这真的是你想要的吗?
他没有什么好的。 – 2009-10-29 13:48:47
不是返回Media对象的yield返回值吗? (不是媒体对象的枚举器)。 – 2009-10-29 13:50:38
枚举器是在调用foreach时创建的状态维护对象,用于跟踪集合中的哪个对象是当前对象,并在每次迭代迭代时将该状态递增到下一个对象。使用yield return时,c#编译器为您创建一个枚举器。 – 2009-10-29 13:53:33
貌似你试图添加Media
实例为Video
集合,它吹起来,因为一个或更多的人是Photo
- 你试图照片添加到视频采集。错误在您的客户端代码中,而不是在生成的枚举器中。
尝试......
class Program
{
static void Main(string[] args)
{
var array = new string[] { "video", "photo", "hurf", "photo" };
var ml = new MediaList(array);
foreach(var element in ml)
Console.WriteLine(element.GetType().Name);
Console.Read();
}
}
public class Media { }
public class Video : Media { }
public class Photo : Media { }
public class MediaList
{
private string[] elements;
public MediaList(string[] elements) { this.elements = elements; }
public IEnumerator<Media> GetEnumerator()
{
foreach (string s in elements)
switch (s)
{
case "video":
yield return new Video();
break;
case "photo":
yield return new Photo();
break;
}
}
}
你可以拍这个到一个控制台应用程序进行测试。
注意到一些不同的东西。 第一个,你永远不会返回null。这与您的问题没有任何关系,但没有人希望枚举返回null,并且稍后会导致您的问题。 第二个,我没有演出我回来的东西。所有的转换都是隐含的,或者由编译器处理,所以我没有必要这样做。 第三,这个编译和工作,你的原始代码。您的问题正在其他地方发生,因为您会发现如果将此代码放入控制台应用程序并进行测试。
+1这是我在开始时的确切代码,直到我把整个错误的兔子都拖下来:-) – Geoff 2009-10-29 14:06:58
媒体摘要? – 2009-10-29 13:37:56
没有媒体不是摘要 – Geoff 2009-10-29 13:39:11
您确定代码完全一样吗?您能否显示客户端代码 - 介绍客户端代码中的(合/对)差异。 – 2009-10-29 13:43:42