使用List 而不是IEnumerable 有什么好处?

或者反过来?

我一直使用通用列表。 但我偶尔也会听到有关IEnumerables的消息,而且老实说我(今天)不知道它们是什么以及我为什么要使用它们。 所以,冒着在网上有东西永远更多地宣扬我的无知的风险,我谦卑地发布这个问题。

好吧, List实现IEnumerable …基本上IEnumerable只是一个项目序列。 你可以通读它,这就是全部。

List是一个可变集合 – 你可以添加它,从中删除,排序等。它本身更灵活,但IEnumerable允许你使用相同的代码来处理任何实现(数组,链接使用yield语句从方法返回的列表,列表,迭代器等)。

IEnumerable是一个更通用的接口,因此您可以替换为您的操作实现该接口的任何内容。 如果你有这个方法:

 public void DoSomething(IEnumerable enumerable) { } 

它将适用于数组,集合,列表,字典以及实现该接口的任何其他内容。

如果指定对象是List ,则该方法仅适用于List对象或从其inheritance的实例。

使用List的优点是列表具有比枚举更多的function。 当您需要这些function(插入,搜索,转换等)时, ListIList更合适。

John Skeet和其他人提供了一个关于List over IEnumerable的function的详细概要,所以我想我会填写问题的另一半,即“使用IEnumerable而不是List有什么好处?”。

首先,IEnumerable提供了一个更通用的合约,用于表示可以迭代的事物集合,因此允许您遵守最小权限原则 。 换句话说,IEnumerable应该优先于其派生类型,其中枚举是需要为手头任务公开的唯一行为。 这是有益的,因为暴露信息和/或行为会不必要地打开您的API,直至可能出现意外用法,这可能会造成安全问题,或者可能导致API与其消费者之间出现意外耦合。

其次,IEnumerable是枚举的抽象,而List是该抽象的一个实现。 遵循设计模式 – 可重用面向对象软件的元素的指导,通过允许实现在以后更改而不影响消耗代码,对实现的抽象编程有助于使应用程序更具弹性。 如果确实需要列表行为,则应直接公开IList而不是List。

List优于IEnumerable的最大优点如下

  1. 随机访问
  2. 伯爵财产
  3. ForEach方法
  4. 可变性

前两个在IEnumerable上也很容易,但你不能保证O(1)的速度。 在Count的情况下,你甚至无法保证真正的答案,因为IEnumerable可以很容易地代表无限列表。

List提供了IEnumerable之外的其他方法。 您不能使用IEnumerable添加插入或删除,但您可以使用List。

当您计划仅循环数据时,应使用IEnumerable。 它为您提供了优于IList的优势,因为您不必一次加载所有数据来传递对数据的访问权限,您只需要能够通过枚举器获取下一条记录。 IEnumerable也是一个接口,因此您可以“隐藏”包含数据List,Array等的实际对象的类型。

如果您只需要在IEnumerable公开和实现的function,那么您应该使用它。 另一种方法是IEnumerable where T : IFoo如果你想能够迭代实现接口IFoo对象。 但是,如果您需要像Count这样的属性以及List公开的属性,那么您应该这样做。 找到最低的共同点,并使用它,因为它使您的方法更通用,更容易使用。

IEnumerable具有干净的只读和“可枚举”或“可查询”语义。 使用List看起来你允许任何人修改它:)。

尚未提及的IEnumerable的一个优点:Contravariance。 如果给出IEnumerable(Of HondaCivic),那么期望IEnumerable(Of Car)的例程将非常高兴,这反过来意味着它会对IList(Of HondaCivic)感到满意。 相比之下,期望IList(Of Car)的例程将不满足IList(HondaCivic)。 如果Microsoft IList是从只读的IReadableByIndex接口派生的,那么期望IReadableByIndex(Of Car)的代码对于IReadableByIndex(Of HondaCivic)非常满意,但那是桥下的水。