簡體   English   中英

為什么 IEnumerable<T> 從 IEnumerable 繼承?

[英]Why does IEnumerable<T> inherit from IEnumerable?

這可能是一個老問題:為什么IEnumerable<T>繼承自IEnumerable

這就是 .NET 的做法,但它帶來了一些麻煩。 每次我寫一個類實現IEumerable<T> ,我必須寫兩個GetEnumerator()函數,一個用於IEnumerable<T> ,另一個用於IEnumerable

而且, IList<T>不繼承自 IList。

我不知道為什么IEnumerable<T>是以其他方式設計的。

直接從馬口(Hejlsberg):

理想情況下,所有泛型集合接口(例如ICollection<T>IList<T> )都將從其非泛型對應物繼承,以便泛型接口實例可以與泛型和非泛型代碼一起使用。 例如,如果可以將IList<T>傳遞給需要IList代碼,那將會很方便。

事實證明,唯一可能的通用接口是IEnumerable<T> ,因為只有IEnumerable<T>是逆變的:在IEnumerable<T> ,類型參數 T 僅用於“輸出”位置(返回值)而不是“輸入”位置(參數)。 ICollection<T>IList<T>在輸入和輸出位置都使用 T,因此這些接口是不變的。 (順便說一句,如果 T 僅用於輸入位置,它們將是逆變的,但這在這里並不重要。)

<...剪...>

因此,為了回答您的問題, IEnumerable<T>繼承自IEnumerable因為它可以! :-)

IEnumerable的答案是:“因為它可以不影響類型安全”。

IEnumerable是一個“只讀”接口——所以通用形式比非通用形式更具體並不重要。 實現兩者都不會破壞任何東西。 IEnumerator.Current返回object ,而IEnumerator<T>.Current返回T - 沒關系,因為您總是可以合法地轉換為object ,盡管它可能意味着裝箱。

將此與IList<T>IList - 您可以在IList上調用Add(object) ,而這對於任何特定的IList<T> (實際上不是IList<object> )很可能無效。

Brad Abram 在博客上寫了 Anders對這個問題的回答。

這是為了向后兼容。 如果您調用一個需要普通 IEnumerable 的 .Net 1.1 函數,您可以傳入您的通用 IEnumerable。

幸運的是,通用 IEnumerator 繼承自舊式 IEnumerator

我通常實現一個私有方法,它返回一個枚舉器,然后將它傳遞給新舊樣式的 GetEnumerator 方法。

    private IEnumerator<string> Enumerator() {
        // ...
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return Enumerator();
    }

這是為了它可以與不支持泛型的類一起使用。 此外,.NET 泛型不允許您執行諸如將 IList<long> 轉換為 IList<int> 之類的操作,因此當您需要固定基類或接口時,接口的非泛型版本可能非常有用。

暫無
暫無

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

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