我有一个名为Media
的基类,有两个继承自它的类,Photo
和Video
。我正在尝试为媒体基类创建一个集合来保存这些照片和视频对象。所以我创建了一个MediaList
类,如下所示:
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 :(得分:3)
试试这个......
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 :(得分:2)
你的错误在别的地方。你写的内容很好,只要Video和Photo都继承Media。也许你正试图在其他地方错误地投射它。
答案 2 :(得分:1)
不应该输入带有yield return的方法来返回IEnumerable<Media>
,而不是IEnumerator<Media>
吗?
但更基本的是,这种模式给我带来了难闻的气味。每次在此“集合”上使用foreach时,您将在Photo
列表中创建(实例化)每个Video
或_mediaElement.Elements()
对象的新实例。这真的是你想要的吗?
答案 3 :(得分:0)
您似乎正在尝试将Media
个实例添加到Video
集合中,并且它会因为其中一个或多个是Photo
而爆炸 - 您正在尝试将照片添加到视频集。错误发生在客户端代码中,而不是生成的枚举器中。