基本上,非泛型接口首先出现在 .NET 1.0 和 1.1 中。然后当 .NET 2.0 出现时,通用的等价物也出现了。如果泛型进入 .NET 1.0,生活会简单得多 :)
就实现“仅”IEnumerable<T>
而不是两者而言 - 您基本上必须同时实现两者,并且您也必须使用显式接口实现,因为两者都定义了无参数GetEnumerator
方法。作为IEnumerator<T>
扩展IEnumerator
,它通常是这样的:
public IEnumerator<T> GetEnumerator()
{
// Return real iterator
}
// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
// Delegate to the generic implementation
return GetEnumerator();
}
另一方面,幸运的是,使用 C# 2(with yield return
etc)中引入的迭代器块,您很少需要完全手动实现这些东西。您可能需要编写类似上面的内容,然后yield return
在GetEnumerator
方法中使用。
注意IList<T>
不扩展,也不扩展。_ _ 那是因为这样做的类型安全性较低……而任何泛型迭代器都可以被视为非泛型迭代器,因为任何值都(可能装箱)转换为,并允许将值添加到集合中;并且将字符串添加(例如)到.IList
ICollection<T>
ICollection
object
IList
ICollection
IList<int>
编辑:我们需要的原因IEnumerable<T>
是我们可以以类型安全的方式进行迭代,并传播该信息。如果我返回一个IEnumerable<string>
给你,你知道你可以安全地假设从它返回的所有内容都是一个字符串引用或空值。使用IEnumerable
,我们必须有效地转换(通常在foreach
语句中隐式地)从序列返回的每个元素,因为 的Current
属性IEnumerator
只是 type object
。至于为什么我们仍然需要IEnumerable
- 因为旧接口基本上永远不会消失。使用它的现有代码太多。
IEnumerable<T>
不扩展是可能的IEnumerable
,但是任何想要使用 an 的代码IEnumerable<T>
都无法调用接受的方法IEnumerable
- 并且有很多类似的方法来自 .NET 1.1 和 1.0。