IEnumerable和IEnumerable之间的区别<t>?</t>

时间:2011-02-11 17:33:44

标签: c# ienumerable generics ilist icollection

IEnumerableIEnumerable<T>之间有什么区别?

我已经看到很多框架类实现了这两个接口,因此我想知道通过实现它们可以获得哪些优势?

请看看它们是如何定义的:

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

正如我们所见,IEnumerable<T>来自IEnumerable,这意味着IEnumerable所拥有的,IEnumerable<T>继承,那么为什么我们实现两者而不仅仅IEnumerable<T> }?实施IEnumerable<T>还不够吗?

同样,还有其他类似的对:

  • IListIList<T>
  • ICollectionICollection<T>

我也想知道这些。

4 个答案:

答案 0 :(得分:55)

基本上,非通用接口首先出现在.NET 1.0和1.1中。然后,当.NET 2.0问世时,通用的等价物就出现了。如果泛型已经进入.NET 1.0,那么生活将变得更加简单:)

在实现“仅”IEnumerable<T>而不是两者中 - 你基本上来实现它们,并且你必须使用显式接口实现,因为它们都定义了无参数{ {1}}方法。由于GetEnumerator也延伸IEnumerator<T>,它通常是这样的:

IEnumerator

另一方面,使用C#2中引入的迭代器块(带public IEnumerator<T> GetEnumerator() { // Return real iterator } // Explicit implementation of nongeneric interface IEnumerator IEnumerable.GetEnumerator() { // Delegate to the generic implementation return GetEnumerator(); } 等),幸运的是,你很少需要完全手工实现这些东西。您可能需要编写类似上面的内容,然后在yield return方法中使用yield return

请注意,GetEnumerator 延伸IList<T>,而IList <{1}}。这是因为它的类型安全性较低......而任何泛型迭代器都可以被视为非泛型迭代器,因为任何值(ICollection<T>ICollection和{{的(可能是装箱)转换1}}允许将值添加到集合中;将(比方说)字符串添加到object

是没有意义的

编辑:我们需要IList的原因是我们可以以类型安全的方式进行迭代,并传播该信息。如果我向您返回ICollection,您就知道您可以安全地假设从它返回的所有内容都是字符串引用或null。使用IList<int>,我们必须有效地(通常隐式地在IEnumerable<T>语句中)强制转换从序列返回的每个元素,因为IEnumerable<string>的{​​{1}}属性只是输入IEnumerable。至于为什么我们仍然需要foreach - 因为旧接口永远不会消失。使用它的现有代码太多了。

Current可能无法扩展IEnumerator,但是任何想要使用object的代码都无法调用接受IEnumerable的方法 - 并且有许多类似于.NET 1.1和1.0的方法。

答案 1 :(得分:7)

一个返回Object类型的对象,另一个返回类型为T的对象。

答案 2 :(得分:2)

至于为什么你看到定义两者的类,尽管IEnumerable&lt; T>实现IEnumerable,它不是必需的,但在自我记录中有时列出子接口是很好的。考虑

interface IA { }
interface IB : IA { }

class A : IB {} // legal, IB implements IA

class B : IA, IB {} // also legal, possible more clear on intent

答案 3 :(得分:1)

在遍历循环时,IEnumerator维持状态。 它会记住光标位置而IEnumerable没有。