簡體   English   中英

嘗試轉換IEnumerable時出現異常?

[英]Exception when attempting to cast IEnumerable?

我還在學習C#項目的前幾周,我正在嘗試正確實現IEnumerable接口。 我已經閱讀了許多教程/指南,但我似乎仍然做錯了什么。 我有一個強大的Java背景,所以我認為我對Java泛型的一些知識讓我理解它們如何在C#中工作。

我無法改變的類包含一個實例變量:

public IEnumerable<object> Items;

我想為它提供一個SampleDataSource類的實例。 此類充當List of MyObject類型的存儲容器:

    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的實例 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>();

我已經意識到這個問題已經回答了,但是我錯過了對你問題背后問題的一個簡單解釋,所以這里有:

您無法將SampleDataSource類分配給IEnumerable<object>字段的原因是SampleDataSource不實現IEnumerable<object> 雖然它確實實現了IEnumerable ,但這還不夠好,因為IEnumerable<object>IEnumerable子類型

由於接口協方差,如果它實現IEnumerable<MyObject> ,您能夠將類分配給IEnumerable<object>字段,前提是MyObject實際上是引用類型(即類)。 但是,這僅適用於C#4.0及更高版本。

Reed Copsey的回答沒有提到你可以聲明SampleDataSource類,因為IEnumerable<T>繼承自IEnumerable

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();  
    }  
}  

但是,從面向對象的角度來看,這是有問題的,因為您正在為列表提供公共讀寫訪問權限。 (setter是私有的這一事實意味着公眾不能重新分配列表引用,但它不會阻止它們在列表上調用AddRemoveClear 。)

另取在面向對象的問題是要問:如果一個SampleDataSource 包含 MyObjects序列,為什么會也是 MyObjects的序列? 而不是這樣做:

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

也許你應該這樣做:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM