使用yield return返回从基类型继承的对象

问题描述:

我有一个名为Media的bas类,其中有两个继承自它的类,PhotoVideo。我正在尝试为媒体基类创建一个集合以容纳这些照片和视频对象。所以,我创建了一个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对象,为什么它抛出异常?有没有更好的方法来解决这个问题?

+0

媒体摘要? – 2009-10-29 13:37:56

+0

没有媒体不是摘要 – Geoff 2009-10-29 13:39:11

+2

您确定代码完全一样吗?您能否显示客户端代码 - 介绍客户端代码中的(合/对)差异。 – 2009-10-29 13:43:42

你的错误是在其他地方。只要Video和Photo从媒体继承,你所写的就没有问题。也许你试图把它错误地放在别的地方。

+0

经过挖掘,你是对的,我的问题在别处。问题在哪里?叹息回到步进代码:-) – Geoff 2009-10-29 14:00:00

不应与收益率回报的方法输入返回IEnumerable<Media>,不IEnumerator<Media>

但更基本,这种模式给我留下难闻的气味。每次你对这个“集”使用的foreach,您将创建(实例)在_mediaElement.Elements()列表中的每个PhotoVideo对象的新实例。这真的是你想要的吗?

+0

他没有什么好的。 – 2009-10-29 13:48:47

+0

不是返回Media对象的yield返回值吗? (不是媒体对象的枚举器)。 – 2009-10-29 13:50:38

+0

枚举器是在调用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,并且稍后会导致您的问题。 第二个,我没有演出我回来的东西。所有的转换都是隐含的,或者由编译器处理,所以我没有必要这样做。 第三,这个编译和工作,你的原始代码。您的问题正在其他地方发生,因为您会发现如果将此代码放入控制台应用程序并进行测试。

+0

+1这是我在开始时的确切代码,直到我把整个错误的兔子都拖下来:-) – Geoff 2009-10-29 14:06:58