这可能是一个老问题:为什么IEnumerable<T>
继承自IEnumerable
?
.NET 就是这样做的,但它带来了一些麻烦。每次我写一个类 implementsIEumerable<T>
时,我都要写两个GetEnumerator()
函数,一个 for ,一个IEnumerable<T>
for IEnumerable
。
而且,IList<T>
不从 IList 继承。
我不知道为什么IEnumerable<T>
以其他方式设计。
这可能是一个老问题:为什么IEnumerable<T>
继承自IEnumerable
?
.NET 就是这样做的,但它带来了一些麻烦。每次我写一个类 implementsIEumerable<T>
时,我都要写两个GetEnumerator()
函数,一个 for ,一个IEnumerable<T>
for IEnumerable
。
而且,IList<T>
不从 IList 继承。
我不知道为什么IEnumerable<T>
以其他方式设计。
直接从马的嘴里(Hejlsberg):
理想情况下,所有泛型集合接口(例如
ICollection<T>
)IList<T>
都将从它们的非泛型对应物继承,这样泛型接口实例既可以与泛型代码一起使用,也可以与非泛型代码一起使用。例如,如果IList<T>
可以将 an 传递给需要IList
.
事实证明,唯一可行的
IEnumerable<T>
通用IEnumerable<T>
接口IEnumerable<T>
是)。ICollection<T>
并IList<T>
在输入和输出位置都使用 T,因此这些接口是不变的。(顺便说一句,如果 T 仅用于输入位置,它们将是逆变的,但这在这里并不重要。)
<...剪辑...>
所以,回答你的问题,IEnumerable<T>
继承自,IEnumerable
因为它可以!:-)
答案IEnumerable
是:“因为它可以在不影响类型安全的情况下”。
IEnumerable
是一个“只读”接口 - 所以泛型形式比非泛型形式更具体并不重要。你不会通过同时实现两者来破坏任何东西。IEnumerator.Current
返回object
,而IEnumerator<T>.Current
返回T
- 没关系,因为您始终可以合法地转换为object
,尽管这可能意味着拳击。
将此与IList<T>
and IList
- 进行比较,您可以调用Add(object)
an IList
,而这可能对任何特定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> 之类的操作,因此当您需要固定的基类或接口时,接口的非泛型版本可能非常有用。