IEnumerable和数组有什么区别?

时间:2010-08-26 16:38:26

标签: c# ienumerable

有人会描述IEnumerable以及IEnumerable和数组之间有什么区别 以及如何使用它的所有信息以及如何使用它。

5 个答案:

答案 0 :(得分:11)

数组是具有设定大小的对象的集合。

int[] array = [0, 1, 2];

这使得它在您可能想要访问集合中特定位置的项目的情况下非常有用,因为已知每个元素的内存中的位置

array[1];

此外,可以快速计算阵列的大小。

另一方面,IEnumerable基本上说,给定一个起始位置,可以获得下一个值。这方面的一个例子可能是一系列无数的数字:

public IEnumerable<int> Infinite()
{
    int i = 0;
    while(true)
        yield return i++;
}

与数组不同,可枚举集合可以是任何大小,并且可以根据需要而不是预先创建元素,这允许强大的构造,并且LINQ广泛使用它来促进复杂查询。

//This line won't do anything until you actually enumerate the created variable
IEnumerable<int> firstTenOddNumbers = Infinite().Where(x => x % 2 == 1).Take(10);

然而,获取特定元素的唯一方法是从头开始并枚举到你想要的那个。这比从预生成的数组中获取元素要贵得多。

当然,您可以通过数组进行枚举,因此数组实现了IEnumerable接口。

答案 1 :(得分:3)

.NET的IEnumerable接口名称错误 - 它应该是IIterable。基本上是System.Collection.IEnumerable或(自generics)System.Collection.Generic.IEnumerable允许您在实现这些接口的对象上使用foreach。

(旁注:实际上.NET正在为foreach使用duck typing,所以你不需要实现这些接口 - 如果你提供合适的方法实现就足够了。)

数组(System.Array)是一种序列(其中序列是指可迭代的数据结构,即实现IEnumerable的任何内容),但有一些重要的区别。

例如,IEnumerable可以 - 并且经常 - 延迟加载。这意味着在您明确迭代它之前,将不会创建项目。如果您不了解它,可能会导致奇怪的行为。 因此,IEnumerable无法告诉您它包含多少项,直到您实际迭代它(System.Linq.Enumerable类中的Count扩展方法)。

一个数组有一个Length属性,有了这个,我们得到了最重要的区别:一个数组,如果是一系列固定(和已知)项。它还提供了一个索引器,因此您可以方便地访问其项目而无需实际迭代它。

只是为了记录,.NET中的“真实”枚举是使用enum关键字定义的类型。它们允许您在不使用幻数或字符串的情况下表达选择。当使用FlagsAttribute标记时,它们也可以用作标志。

我建议您使用您喜欢的搜索引擎来获取有关这些概念的更多详细信息 - 我的简要摘要显然并非旨在深入了解这些功能。

答案 2 :(得分:2)

Array是一组数据。这意味着这些商品是连续存储的,并且可以直接存储。

IEnumerable是数据集合的描述。它们本身不是收藏品。具体来说,这意味着可以逐步执行集合,一次一个项目。

如果将变量定义为IEnumerable类型,则它可以引用符合该描述的任何类型的集合。

数组是可枚举的。 Lists,Dictionaries,Sets和其他集合类型也是如此。此外,似乎不是集合的东西可以是Enumerable,例如字符串(IEnumerable<char>),或Enumerable.Range()返回的对象,它为每个步骤生成一个新项目实际上把它拿在任何地方。

答案 3 :(得分:2)

<强>阵列

<。> .Net数组是连续存储在内存中的多个值的集合。数组中的各个元素可以通过索引随机访问(这样做非常有效)。数组的重要成员是:

  • this[Int32 index](索引运算符)
  • Length

C#内置了对数组的支持,可以直接从代码初始化它们:

var array = new[] { 1, 2, 3, 4 };

数组也可以是多维的,并实现多个接口,包括IEnumerable<T>(其中T是数组的元素类型)。

<强>的IEnumerable&LT; T&GT;

IEnumerable<T>接口定义方法GetEnumerator(),但该方法很少直接使用。相反,foreach循环用于遍历枚举:

IEnumerable<T> enumerable = ...;
foreach (T element in enumerable)
  ...

如果枚举是在数组或列表上完成的,枚举中的所有元素都存在,但也可以枚举动态创建的元素。 yield return构造对此非常有用。

可以从枚举中创建一个数组:

var array = enumerable.ToArray();

这将获取枚举中的所有元素,并将它们连续存储在单个数组中。

总结一下:

  • 数组是可以通过索引
  • 随机访问的元素集合
  • 枚举是对一系列元素的抽象,这些元素可以以前进的方式一个接一个地访问

答案 4 :(得分:1)

有一点是Arrays允许随机访问某些固定大小的内容。 IEnumerable接口按顺序提供数据的位置,您可以一次从IEnumerable中提取数据,直到数据源耗尽。