我应该返回IEnumerable还是IList?

Ben*_*Ben 38 c# collections ienumerable

我希望从方法中返回一个有序的项目列表.我的返回类型应该是IEnumerable还是IList?

Hen*_*man 42

这里有一个层次结构:

interface IList<T> : ICollection<T> { } 
interface ICollection<T> : IEnumerable<T> { }
Run Code Online (Sandbox Code Playgroud)

你想瞄准尽可能少的耦合,所以IEnumerable<T>如果这足够就返回.它可能会.

IList<T>如果情况需要调用者获得可用于添加/插入/删除的List,则返回an .但即便如此,如果调用者从IEnumerable集合创建自己的List也可能会更好.

  • 使用IEnumerable时,函数ElementAt和Count怎么样?我知道每次调用ElementAt时,循环都会遍历整个列表,直到找到元素.这与使用Count的行为相同,只是它在整个列表中循环.除了添加,删除和插入之外,还应考虑使用列表.我错了吗? (3认同)

Ale*_*rey 13

这取决于你想要对结果做什么.如果您需要获取项目数或随机访问单个项目,请使用IList.

如果调用者只想迭代这些项,那么请使用IEnumerable - 但是你应该记录是否会延迟评估返回的值 - 这些天的许多IEnumerable实例表示在枚举集合时将执行的查询.为了安全起见,如果您要归还的内容不会按需评估,我会选择IList.


Joe*_*ite 6

一般来说,最好 return IEnumerable<T>,只要它有调用者需要的一切。

IEnumerable<T>是 foreachable,这是许多消费者所需要的。它也是只读的,这通常是一件好事——这意味着您有时可以通过返回实际的支持集合进行优化,而不必担心有人在不告诉您的情况下对其进行了修改。

但是,如果消费者需要不在 上的方法IEnumerable<T>,那么IList<T>可能更有意义。例如,调用者可能想要调用Contains,而该调用不在 上IEnumerable<T>。或者调用者可能想要索引到列表中,而不是从头到尾迭代它。

但是您也可以IEnumerable<T>通过 LINQ 的ContainsElementAt扩展方法进行包含和索引。所以这里有一个学位问题。如果调用者只需要问一个在 上不可用的问题IEnumerable<T>,例如“这是空的”,则返回 anIEnumerable<T>并使用Any扩展方法。但是如果调用者IList<T>广泛使用操作,则返回IList<T>

  • @Oliver,你说“总是”是错误的。LINQ Contains 和 ElementAt 首先尝试将集合转换为 `ICollection&lt;T&gt;` / `IList&lt;T&gt;`,以便它们可以为您调用 O(1) 方法。O(n) 实现仅在失败时使用。如果你返回一个类型为 `IEnumerable&lt;T&gt;` 的 `List&lt;T&gt;`,那么 Contains 和 ElementAt 仍然是 O(1),尽管有一些额外的开销。您可以在 Reflector 中确认这一点。 (6认同)

cRi*_*ter 5

它很容易,如果调用者只应该使用Readonly,则使用IEnumerable.因为这也支持协方差(结果可以转换为基类型)

  • 实际上,它是协变的,但很重要. (2认同)