![](/img/trans.png)
[英]Why is GetEnumerator not visible in COM for .Net classes that inherit from IEnumerable<T>?
[英]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.