为什么IEnumerable<;T>;从IEnumerable继承
本文关键字:IEnumerable 继承 gt lt 为什么 | 更新日期: 2023-09-27 17:48:48
这可能是一个老问题:为什么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
的答案是:"因为它可以在不影响类型安全的情况下";。
CCD_ 21是";只读";接口-所以泛型形式比非泛型形式更具体并不重要。实现这两者不会破坏任何东西。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函数,则可以传入您的通用IEnumeraable。
幸运的是,通用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>,因此当您需要固定基类或接口时,非泛型版本的接口可能非常有用。