关于c#:IEnumerable和Array,IList和List之间有什么区别?


What's the difference between IEnumerable and Array, IList and List?

IEnumerableArray有什么区别?

IListList有什么区别?

它们似乎有相同的功能。


IEnumerable只提供最小的"Iterable"功能。你可以遍历序列,但就是这样。这有缺点——例如,使用IEnumerable计算元素或获取第n个元素效率很低——但它也有优点——例如,IEnumerable可以是一个无止境的序列,就像素数序列一样。

数组是一个具有随机访问的固定大小的集合(即,可以对其进行索引)。

列表是一个具有随机访问的可变大小集合(即可以添加和删除元素)。

IList是一个接口,它将列表功能(计数、添加、删除、索引器访问)从各种具体类(如List、BindingList、ObservableCollection等)中抽象出来。


IEnumerable是一个接口,允许通过项目集合(例如通过foreach关键字)进行迭代。

数组是.NET内部函数。它可以容纳相同类型的物品,但大小固定。一旦用x元素创建了一个数组,它就不能增长或收缩。

IList为列表定义接口,并实现IEnumerable。

列表实现了IList接口;它是列表的具体类型。

.NET列表和数组之间的区别在于,列表中可以添加元素——它们会变得足够大,可以容纳所有必需的项。列表在内部将其存储在一个数组中,当数组不再大到足以容纳所有元素时,将创建一个新数组,并跨其复制项。

IList和数组都实现IEnumerable。接口就是这样工作的——类实现契约并以类似的方式工作,因此可以类似地对待(您知道类实现IEnumerable,您不需要知道如何或为什么)。我建议你仔细阅读一下界面等等。


IEnumerable和IList是接口。数组和列表是类。数组实现IEnumerable。List实现扩展IEnumerable的IList。

编辑:正如Itowlson在注释中提到的,数组也实现了IList。


生成IEnumerable集合是懒惰的。例子:

1
2
3
4
5
6
7
8
9
public IEnumerable<int> GetTwoInts()
{
  yield return 1;
  yield return 2;
}
public void Something()
{
  var twoInts = GetTwoInts();
}

在方法中,对gettwoints()的调用实际上不会导致方法gettwoints被执行,因为枚举从未被迭代过。


IEnumerable是一个通用接口,许多类(如ArrayListString使用它来让某人迭代集合。基本上,这就是驱动foreach声明的原因。

IList通常是向最终用户公开List类型变量的方式。此接口允许随机访问基础集合。


为了补充其他答案,请注意在执行foreach语句时,IListList之间存在性能差异。

这是因为List.GetEnumerator返回的迭代器对象是值类型,而IList.GetEnumerator返回的迭代器对象是引用类型,因此需要内存分配(参见c中列表值类型的枚举器)。

在我看来,IList无论如何都不是一个很好的接口。例如,调用Add可以抛出(参见数组为什么实现ilist?)如果需要封装,最好使用IEnumerableIReadOnlyList


这是一篇旧文章,但仍在考虑回复。IEnumerable是一种行为,而数组是一种数据结构(具有固定大小的元素的连续集合,便于通过索引访问元素)。当数组实现IEnumerable时,它还应该描述IEnumerable的固有属性(便于在集合上迭代)。