我希望从一个方法中返回一个有序列表。我的返回类型应该是IEnumerable还是IList?
我希望从一个方法中返回一个有序列表。我的返回类型应该是IEnumerable还是IList?
这里存在一个层次结构:
interface IList<T> : ICollection<T> { }
interface ICollection<T> : IEnumerable<T> { }
为了达到最小程度的耦合,如果能够满足需求,就应该返回一个 IEnumerable<T>
。这通常已经足够了。
如果情况需要调用者获得可以用于添加/插入/删除的列表,则应返回一个 IList<T>
。但即使如此,调用者从 IEnumerable 集合中创建自己的 List 可能会更好。
需要看你希望对结果做什么操作。如果需要获取项的数量或随机访问单个项,请选择IList。
如果调用方只是想遍历项目,则使用IEnumerable - 但是你应该记录返回的值是否被惰性地评估 - 许多IEnumerable实例今天表示在枚举集合时将执行查询。为了安全起见,如果你返回的内容不会按需求被评估,我会选择IList。
IEnumerable<T>
,只要它包含调用方所需的所有内容。
IEnumerable<T>
可以使用 foreach 循环,这对于许多消费者来说已经足够了。它也是只读的,这通常是一件好事 - 这意味着您有时可以通过返回实际的后备集合来进行优化,而不必过多担心有人在未告知您的情况下修改它。IEnumerable<T>
上,那么 IList<T>
可能更合适。例如,调用方可能想调用 Contains
,它不在 IEnumerable<T>
上。或者调用方可能想要索引列表,而不是从头到尾迭代它。IEnumerable<T>
上执行 Contains 和索引操作。因此,在这里存在一个程度问题。如果调用方只需要询问一个不在 IEnumerable<T>
上的问题,比如“这是空的吗”,则返回 IEnumerable<T>
并使用 Any 扩展方法。但是,如果调用方广泛使用 IList<T>
操作,则返回 IList<T>
。ICollection<T>
/IList<T>
接口,以便为您调用O(1)方法。只有在尝试失败时才会使用O(n)实现。如果您返回的是以IEnumerable<T>
类型定义的List<T>
,那么Contains和ElementAt仍然是O(1),但会稍微增加一些开销。您可以在Reflector中确认这一点。 - Joe White如果调用者只需使用只读数据,则使用IEnumerable很容易。因为它还支持协变(结果可以转换为基础类型)。
IList<T>
的集合也是如此,因为它具有索引器。任何不保持顺序的集合都将在其文档中声明,例如Dictionary<TKey, TValue>.KeyCollection
或HashSet<T>
。 - Joe WhiteIEnumerable比IList更不具体,也就是说,IList具有IEnumerable没有的功能。
比较这两个接口,看看它们是否有你需要而另一个没有的功能。
IList拥有改变元素的方法(如Add),也许您想在ICollection和IEnumerable之间进行选择。
ICollection扩展了IEnumerable,并且具有可用的Count属性,这可能会很有用。
Parallel.
和其他线程时,开始在与来自存储库的IEnumarbales一起工作的服务中引起了我巨大的头痛。我的观点是:除非您正在从前端过滤上下文(我们都知道这很糟糕),否则不应该在数据上下文之外使用或传递IEnumarble。因此,请放弃IEnumarble并开始使用IList
。 - Piotr Kula