C# 为什么使用ICollection<;T>;超过IList<;T>;?

C# 为什么使用ICollection<;T>;超过IList<;T>;?,c#,list,ienumerable,icollection,C#,List,Ienumerable,Icollection,我读过一些文章说,如果想要IEnumerable的功能,还需要Count属性,那么就使用ICollection 但是,既然System.Linq.Enumerable中的扩展方法提供了ElementAt()之类的方法,为什么不使用IList,因为它使用索引器呢 在我看来,ICollection可以做IList可以做的事情,只是用了一种更详细、可读性更低的方式 什么样的场景更具可读性/效率更高,更符合坚实的原则,或者使用ICollection优于IList 编辑: 重复问题的答案不能回答我的问题,

我读过一些文章说,如果想要
IEnumerable
的功能,还需要
Count
属性,那么就使用
ICollection

但是,既然
System.Linq.Enumerable
中的扩展方法提供了
ElementAt()
之类的方法,为什么不使用
IList
,因为它使用索引器呢

在我看来,
ICollection
可以做
IList
可以做的事情,只是用了一种更详细、可读性更低的方式

什么样的场景更具可读性/效率更高,更符合坚实的原则,或者使用
ICollection
优于
IList

编辑:

重复问题的答案不能回答我的问题,因为它们避免谈论
ICollection
可以做
IList
所做的事情,但方式更丑陋

如果它们都做相同的事情,为什么不使用cleaner
IList

我在这里得到了更好的答案:

如果您从开销的角度来看,我认为您最好的选择是充当两者之间的中介,它是
HashSet
的实现

集合经常被忽略,但由于不依赖于键,因此在确定“所有权”和节省空间方面非常有效,因为它们不关心排序

编辑(2020/11/18)需要注意的是,在向哈希集中添加一个项时,将计算该项的哈希代码。这样做的成本可能很高,因此完全否定了您可能从更快的查找中获得的任何性能优势

重要的区别在于
Add()
Remove()
Contains()
都变成了o(1)(与
IList
通常的o(n)成本相比)

如果订购成为一个问题,也会出现
SortedSet

这里有一个很好的解释,这比我能解释的要深刻得多。一个重要的片段:

如果您想要尽可能快的查找,但不关心顺序,
HashSet
是您的选择集。相反,
SortedSet
将在性能稍有降低的情况下为您提供排序的集合


简短的回答是,您可以对任何元素列表使用IList。事实上,IList实现了ICollection,ICollection实现了IEnumerable。您可以根据上下文决定所需的抽象级别


有关详细信息,请参阅。

答案非常主观。更多的是关于你需要多少

  • 如果您只需要遍历所有项目,请选择
    IEnumerable
  • 如果需要手动填充集合(
    Add
    Remove
    等),则应使用
    ICollection
  • 如果要经常使用索引,请使用
    IList
  • 如果您计划进行各种操作,请继续使用
    List
但是,在这些情况下,有
ireadonlycollection
IReadonlyList
,这使得返回的集合是不可变的,并且应该位于IEnumerable之后,但优先于
ICollection
IList

最终目标始终是尽可能使用抽象类型。这是基于接口的原则
代码,而不是实现的原则


编辑:对于这个问题,我想说索引的需要是优先选择其中一个的主要因素。

那么你是说我可以调用你的方法或读取你的属性,获取一个列表,然后开始向其中添加元素?你的问题中涉及的三种类型告诉我不同的事情。IEnumerable告诉我,我将获得一个f items.ICollection告诉我,我将获得一个项目集合,以确保轻松快速地访问其中的项目数。列表告诉我,我将获得一个可以操纵的集合。您必须决定在每种情况下哪个级别是合适的。但ICollection也为您提供了一个可以操纵的集合。ICollection似乎就是这样具有与IList相同的功能,只是没有那么干净。不幸的是,我觉得这个问题离题了,因为它间接地征求了人们的意见和建议。没有固定可靠的单一答案说“在其他事情发生时返回这个”.我有几个意见,只是关于你是否应该返回一个或另一个,这取决于很多因素,但归根结底是我的意见。我认为你的问题实际上是一个重复的问题,这些答案(广义上)解决了这一问题-这是一个用例场景。其中一个场景是使用
IDictionary
dynamic
类型(
System.Dynamic.ExpandoObject
)就这一点而言。好吧……我不会投你的反对票(鉴于你的代表),但这里的问题陈述反映了标题:"使用
ICollection
而不是
IList
会是什么样的场景呢?因此,这个答案与问题和查询都不相关。此外,您可能应该使用诸如“实现”甚至“派生”之类的术语,而不是子接口来与我们更习惯的OOP材料相关。此外,这也值得怀疑你是否应该以分层的方式来考虑接口。我实际上还没有深入研究到足以给出确定性,但归根结底,你是否能够在运行时确定是否存在某种类型的实例的基础接口的派生接口;如果有可能做到这一点,我可以看到思考的好处在这些方面。感谢@brett caswell的评论。相应地更新了答案。有争议的意见。当我打算多次迭代可枚举项时,我要求使用
IReadOnlyCollection
。我还制作了不能多次迭代的可枚举项。多次枚举以及无序枚举