返回'IList'与'ICollection'对比'收集'

Roc*_*ngh 112 .net c# generics collections

我很困惑我应该从我的公共API方法和属性返回哪种集合类型.

我想到的收藏品是IList,ICollectionCollection.

返回其中一种类型总是优先于其他类型,还是取决于具体情况?

cor*_*erm 134

ICollection<T>是暴露集合语义诸如接口Add(),Remove()Count.

Collection<T>ICollection<T>接口的具体实现.

IList<T>本质上是一个ICollection<T>随机的基于订单的访问.

在这种情况下,您应该决定您的结果是否需要列表语义,例如基于订单的索引(然后使用IList<T>),或者您是否只需要返回无序的"包"结果(然后使用ICollection<T>).

  • .Net中的所有集合都是有序的,因为`IEnumerable <T>`是有序的.区分`IList <T>`与`ICollection <T>`的区别在于它为成员提供索引.例如`list [5]`有效,但`collection [5]`不会编译. (54认同)
  • `Collection <T>`实现`IList <T>`而不仅仅是`ICollection <T>`. (5认同)
  • 我也不同意有序集合应该实现`IList <T>`.有很多有序的集合没有.`IList <T>`是关于快速索引访问的. (5认同)
  • @svick:是否订购了所有集合,因为`IEnumerable <T>`是有序的?把`HashSet <T>` - 它实现`IEnumerable <T>`但显然没有订购.即你对项目的顺序没有影响,如果内部哈希表被重新组织,这个顺序可能随时改变. (5认同)
  • @yoyo .net集合类和接口设计简单,命名错误.我不会想太多为什么他们这样命名他们. (3认同)
  • +1为一个好的答案.但是,我建议添加一些关于抽象的一般原则的注释,以及为什么它有利于返回接口类型而不是具体的类类型. (2认同)

Guf*_*ffa 68

通常,您应该返回尽可能通用的类型,即只知道消费者需要使用的返回数据的类型.这样,您可以更自由地更改API的实现,而不会破坏使用它的代码.

还将IEnumerable<T>接口视为返回类型.如果仅对结果进行迭代,则消费者不需要更多.

  • 但也要考虑ICollection <T>,它扩展IEnumerable <T>以提供包括Count属性在内的其他实用程序.这可能很有用,因为您可以在不多次遍历序列的情况下确定序列的长度. (23认同)
  • @retrodrone:实际上`Count`方法的实现会检查集合的实际类型,所以即使你把它作为一个已知的类型,例如数组和`ICollection`,它也会使用`Length`或`Count`属性. `IEnumerable`. (9认同)
  • @Guffa:值得注意的是,如果一个类`Thing <T>`实现`IList <T>`而不是非泛型`ICollection`,那么调用`IEnumerable <Cat> .Count()` `Thing <Cat>`会很快,但调用`IEnumerable <Animal> .Count()`会很慢(因为扩展方法会寻找,而不是找到`ICollection <Cat>`的实现).但是,如果类实现了非泛型的`ICollection`,那么`IEnumerable <Animal> .Count`会找到并使用它. (7认同)
  • 我不同意.最好返回您拥有的最丰富的类型,以便客户端可以直接使用它,如果这是他们想要的.如果你有一个List <>,为什么只返回一个IEnuerable <>来强制调用者不必要地调用ToList()? (5认同)
  • [MSDN 链接到 Enumerable.Count](http://msdn.microsoft.com/en-us/library/vstudio/bb338038(v=vs.90).aspx) (2认同)

Oli*_*bes 57

IList<T>和之间的主要区别ICollection<T>IList<T>允许您通过索引访问元素.IList<T>描述类似数组的类型.ICollection<T>只能通过枚举访问can中的元素.两者都允许插入和删除元素.

如果您只需要枚举一个集合,那么IEnumerable<T>首选.它有两个优点:

  1. 它不允许更改集合(但不允许更改为引用的对象,如果它们是引用类型).

  2. 它允许尽可能多种来源,包括通过算法生成的枚举,而不是集合.

Collection<T>是一个基类,主要用于集合的实现者.如果在接口(API)中公开它,将排除许多不是从它派生的有用集合.


一个缺点IList<T>是数组实现它但不允许你添加或删除项目(即你不能改变数组长度).如果调用IList<T>.Add(item)数组,则会抛出异常.这种情况有点解散,因为IList<T>有一个布尔属性IsReadOnly,您可以在尝试之前检查它.但在我看来,这仍然是图书馆的设计缺陷.因此,List<T>当需要添加或删除项目的可能性时,我直接使用.


Nul*_*nce 6

IList<T>是所有通用列表的基本接口.由于它是有序集合,因此实现可以决定排序,从排序顺序到排序顺序.此外,Ilist还具有Item属性,允许方法根据索引读取和编辑列表中的条目.这使得可以在位置索引处向列表中插入值或从列表中删除值.

此外IList<T> : ICollection<T>,所有方法ICollection<T>也可在此处实施.

ICollection<T>是所有泛型集合的基本接口.它定义了大小,枚举器和同步方法.您可以在集合中添加或删除项目,但由于缺少index属性,您无法选择它在哪个位置发生.

Collection<T>提供了一个实现IList<T>,IListIReadOnlyList<T>.

如果使用较窄的接口类型(例如ICollection<T>代替)IList<T>,则可以保护代码免受更改.如果使用更宽的接口类型IList<T>,则更容易破坏代码更改.

引自来源,

ICollection,ICollection<T>:您想要修改集合,或者您关心它的大小. IList,IList<T>:您想要修改集合,并且您关心集合中元素的排序和/或定位.


Ala*_*lan 5

返回接口类型更通用,因此(缺少有关您的特定用例的更多信息)我倾向于这样做。如果要公开索引支持,请选择IList<T>,否则ICollection<T>就足够了。最后,如果要指示返回的类型是只读的,请选择IEnumerable<T>

而且,如果您以前没有读过它,Brad Abrams 和 Krzysztof Cwalina 写了一本名为“框架设计指南:可重用 .NET 库的约定、习语和模式”的好书(您可以从这里下载摘要)。