C# 使用yield return返回从基类型继承的对象
我有一个名为C# 使用yield return返回从基类型继承的对象,c#,generics,collections,C#,Generics,Collections,我有一个名为Media的bas类,它继承了两个类,Photo和Video。我正在尝试为媒体基类创建一个集合来保存这些照片和视频对象。因此,我创建了一个MediaList类,如下所示: public class MediaList: ICollection<Media> { private readonly XElement _mediaElement; public MediaList(XElement mediaElement) { _me
Media
的bas类,它继承了两个类,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
}
公共类媒体列表:ICollection
{
私有只读XElement _mediaElement;
公共媒体列表(XElement mediaElement)
{
_mediaElement=mediaElement;
}
公共IEnumerator GetEnumerator()
{
foreach(_mediaElement.Elements()中的XElement元素)
{
媒体;
开关(element.Name.LocalName)
{
案例“视频”:
媒体=新视频(元素);
打破
案例“照片”:
媒体=新照片(元素);
打破
违约:
媒体=空;
打破
}
产量回收介质;
}
}
//ICollection实现的其余部分
}
当我迭代列表时,我得到以下异常:
值“Tool.Photo”不是“Tool.Video”类型,不能在此常规集合中使用
如果我返回一个
媒体
对象,为什么它会抛出异常?有没有更好的方法来解决这个问题?是否应该将收益率返回的方法键入returnIEnumerable
,而不是IEnumerator
但更基本的是,这种模式让我有一股难闻的气味。每次在此“集合”上使用foreach时,您都将在
\u mediaElement.Elements()
列表中创建(实例化)每个照片
或视频
对象的新实例。这真的是您想要的吗?看起来您正试图将媒体
实例添加到视频
集合中,但由于其中一个或多个实例是照片
——您正试图将照片添加到视频集合中,因此失败。错误在您的客户端代码中,而不是在生成的枚举数中。您的错误在别处。只要视频和照片都是从媒体继承下来的,你写的东西就可以了。也许你试图在其他地方错误地使用它。试试这个
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;
}
}
}
类程序
{
静态void Main(字符串[]参数)
{
var数组=新字符串[]{“video”、“photo”、“hurf”、“photo”};
var ml=新媒体列表(数组);
foreach(变量元素,单位为ml)
Console.WriteLine(element.GetType().Name);
Console.Read();
}
}
公共类媒体{}
公开课视频:媒体{}
公开课照片:媒体{}
公共类媒体列表
{
私有字符串[]元素;
公共媒体列表(字符串[]元素){this.elements=elements;}
公共IEnumerator GetEnumerator()
{
foreach(元素中的字符串s)
开关
{
案例“视频”:
返回新视频();
打破
案例“照片”:
返回新照片();
打破
}
}
}
您可以将其插入控制台应用程序进行测试
注意两件不同的事情首先,您永远不会返回空值。这与您的问题没有任何关系,但是没有人希望枚举返回null,这将在以后给您带来问题第二次,我不会投出我所返回的。所有的转换都是隐式的或由编译器处理的,所以我不需要这样做第三个,与原始代码一样编译并工作。您的问题发生在其他地方,如果您将此代码放入控制台应用程序并进行测试,您会发现。没有媒体不是抽象的。您确定代码完全正确吗?你能展示一下客户代码吗?客户代码中的一个(co/contra)变量。很高兴你找到了你的答案,但看看我的答案。您的代码存在一些样式问题,其中最重要的是从迭代器返回null。您需要显示错误所在的行,以及媒体、照片和视频的定义。yield返回的不是媒体对象吗?(不是媒体对象的枚举器。)枚举器是在调用foreach跟踪集合中的哪个对象是当前对象时创建的状态维护对象,并在foreach每次迭代时将该状态增加到下一个状态。使用yield return时,c#编译器会为您创建一个枚举器。在正常情况下,我同意您的看法,但在这种情况下,媒体对象只是权值,集合只迭代一次。也许我不清楚,但GetEnumerator()方法的返回类型(您作为IEnumerator使用)不清楚仍然需要是收益回报(IEnumerable)所需的回报类型?我的意思是,如果该方法要返回IEnumerator,其中GetEnumerator()中是一个实现正在构造的IEnumerator的对象??您的收益率返回视频或照片对象。视频类和照片类是否实现IEnumerator??我认为不是……在四处挖掘之后,你是对的,我的问题在别处。问题是在哪里?叹气回到逐步通过代码:-)+1这正是我在开始时的代码,直到我走错了方向:-)