尝试投射IEnumerable时出现异常?

问题描述:

我仍然在学习C#的项目我的头几周,我试图正确地执行IEnumerable接口。我已经阅读了一些教程/指南,但我似乎仍然在做一些不正确的事情。我有一个强大的Java背景,所以我认为我对Java泛型的一些了解让我理解他们如何在C#中工作。尝试投射IEnumerable时出现异常?

一类我不能改变包含一个实例变量:

public IEnumerable<object> Items;

而且我想提供它与我的SampleDataSource类的一个实例。此类充当一个MyObjectList类型的存储容器:

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类的实例IEnumerable<object>使用此代码:

Items = (IEnumerable<MyObject>)App.SampleData; 

我收到异常:

其他信息:无法投射类型的对象'Expression.Blend.SampleData.SampleDataSource.SampleDataSource' 到 类型 'System.Collections.Generic.IEnumerable`1 [Expression.Blend.SampleData.SampleDataSource.MyObject]'。

但我不明白为什么 - 不是我SampleDataSource正确充当IEnumerable返回包含MyObject类型枚举?

它不能只是实现方法,而是具有实际实现的接口。

在你的情况,它会更好,只是让你的类实现相应的接口。

public class SampleDataSource : IEnumerable<MyObject>, IEnumerable 

否则,您可以使用类似linfu的东西来鸭子键入您的类到界面。

的其他潜在目的是利用OfType<T>来处理这个问题:

// returns enumerable of the items that are actually assignable to MyObject 
IEnumerable<MyObject> values = theDataSource.OfType<MyObject>(); 
+0

你能更具体?它在这里没有正确实现接口:`SampleDataSource:IEnumerable`? – 2011-12-16 00:32:21

我意识到这个问题已经回答了,但我错过了你的问题背后的问题的一个简单的解释,所以这里有云:

你不能你SampleDataSource类分配给一个IEnumerable<object>场的原因是,SampleDataSource没有实现IEnumerable<object>。虽然它确实实现IEnumerable,这还不够好,因为IEnumerable<object>亚型IEnumerable

由于接口协方差的,你将能够将类指定给IEnumerable<object>字段是否实现IEnumerable<MyObject>,条件是为MyObject实际上引用类型(即,一类)。这仅适用于C#4。0和更高版本,但是。

里德·科普塞的回答并没有提到,你可以这样声明SampleDataSource类,因为从IEnumerableIEnumerable<T>继承:

public class SampleDataSource : IEnumerable<MyObject> 

而且,因为你只是包裹包含集合,你通常会实现它因此:

public class SampleDataSource : IEnumerable<MyObject> 
{ 
    public List<MyObject> Subjects { get; private set; } 

    public IEnumerator<MyObject> GetEnumerator() 
    { 
     return Subjects.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

这是从面向对象的角度有问题,不过,因为你给到列表中的公共读写访问。 (事实上​​,二传手是私有意味着公众无法重新分配名单参考,但并不妨碍他们从名单上调用AddRemoveClear。)

另取在面向对象的问题会问:如果一个SampleDataSource 包含的一个MyObjects序列,为什么它也会的一个MyObjects序列?相反,这样做的:

classICannotAlter.Items = (IEnumerable<object>)someSampleDataSourceInstance; 

也许你应该这样做:

classICannotAlter.Items = (IEnumerable<object>)someSampleDataSourceInstance.Subjects;