尝试强制转换 IEnumerable 时出现异常?
我仍处于为项目学习 C# 的前几周,并且正在尝试正确实现 IEnumerable
接口。我已经阅读了许多教程/指南,但我似乎仍然做错了一些事情。我有很强的 Java 背景,所以我认为我对 Java 泛型的一些了解混淆了我对它们在 C# 中如何工作的理解。
我无法更改的类包含一个实例变量:
public IEnumerable
我想为其提供我的 SampleDataSource
类的实例。此类充当 MyObject
类型的 List
的存储容器:
public class SampleDataSource : IEnumerable
{
public List<MyObject> Subjects { get; private set; }
public IEnumerator<MyObject> GetEnumerator()
{
return this.Cast<MyObject>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
但是当我尝试转换此 SampleDataSource< 的实例时使用以下代码将 /code> 类转换为
IEnumerable
Items = (IEnumerable<MyObject>)App.SampleData;
我收到异常:
附加信息:无法转换类型的对象 'Expression.Blend.SampleData.SampleDataSource.SampleDataSource' 到 类型 'System.Collections.Generic.IEnumerable`1[Expression.Blend.SampleData.SampleDataSource.MyObject]'。
但我不太明白为什么 - 我的 SampleDataSource
不能正确充当返回包含 MyObject
类型的枚举器的 IEnumerable
吗?
I'm still in my first couple weeks of learning C# for a project, and I'm trying to properly implement the IEnumerable
interface. I've read a number of tutorials/guidelines, but I still seem to be doing something incorrectly. I have a strong Java background, so I think some of my knowledge of Java generics is muddling my understanding how they work in C#.
A class that I cannot alter contains an instance variable:
public IEnumerable<object> Items;
And I'd like to provide it with an instance of my SampleDataSource
class. This class acts as a storage container for a List
of MyObject
types:
public class SampleDataSource : IEnumerable
{
public List<MyObject> Subjects { get; private set; }
public IEnumerator<MyObject> GetEnumerator()
{
return this.Cast<MyObject>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
But when I attempt to cast an instance of this SampleDataSource
class to an IEnumerable<object>
using this code:
Items = (IEnumerable<MyObject>)App.SampleData;
I receive an exception:
Additional information: Unable to cast object of type
'Expression.Blend.SampleData.SampleDataSource.SampleDataSource' to
type
'System.Collections.Generic.IEnumerable`1[Expression.Blend.SampleData.SampleDataSource.MyObject]'.
But I don't quite understand why - isn't my SampleDataSource
properly acting as an IEnumerable
that returns an enumerator containing MyObject
types?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
它不能只实现方法,而必须实际实现接口。
对于您的情况,最好让您的类实现适当的接口。
否则,您可以使用 linfu 之类的方法将您的类鸭式输入到接口中。
另一个潜在的对象是使用
OfType
来处理此问题:It can't just implement the methods, but rather has to actually implement the interface.
In your case, it'd be better to just make your class implement the appropriate interface.
Otherwise, you can use something like linfu to duck-type your class to the interface.
The other potential object is to use
OfType<T>
to handle this:我意识到问题已经得到解答,但我错过了问题背后问题的简单解释,所以这里是:
您无法将
SampleDataSource
类分配给IEnumerable
由于接口协变,如果该类实现了
IEnumerable
,您将能够将该类分配给IEnumerable字段,前提是该类实现了
IEnumerable
MyObject 实际上是一个引用类型(即一个类)。不过,这仅适用于 C# 4.0 及更高版本。Reed Copsey 的答案没有提到您可以这样声明 SampleDataSource 类,因为
IEnumerable
继承自IEnumerable
:此外,因为您只是包装所包含的集合,您通常会这样实现它:
不过,从面向对象的角度来看,这是有问题的,因为您授予了对该列表的公共读写访问权限。 (事实上,setter 是私有的,这意味着公众无法重新分配列表引用,但这并不能阻止他们调用
Add
或Remove
或清除列表上的
。)关于面向对象问题的另一个问题是问:如果 SampleDataSource包含 MyObjects 序列,为什么它也会成为 MyObject 序列?而不是这样做:
也许你应该这样做:
I realize the question is answered already, but I missed a simple explanation of the problem behind your question, so here goes:
The reason you cannot assign your
SampleDataSource
class to anIEnumerable<object>
field is thatSampleDataSource
does not implementIEnumerable<object>
. While it does implementIEnumerable
, that's not good enough, becauseIEnumerable<object>
is a subtype ofIEnumerable
.Because of interface covariance, you will be able to assign the class to the
IEnumerable<object>
field if it implementsIEnumerable<MyObject>
, provided that MyObject is in fact a reference type (i.e., a class). That's only applicable to C# 4.0 and later, however.Reed Copsey's answer doesn't mention that you could declare the SampleDataSource class thus, because
IEnumerable<T>
inherits fromIEnumerable
:Further, since you're just wrapping the contained collection, you would normally implement it thus:
This is questionable from an object-orientation perspective, though, since you're giving the public read-write access to the list. (The fact that the setter is private means that the public can't reassign the list reference, but it doesn't prevent them from calling
Add
orRemove
orClear
on the list.)Another take on the object orientation question would be to ask: if a SampleDataSource contains a sequence of MyObjects, why would it also be a sequence of MyObjects? Instead of doing this:
maybe you should be doing this: