返回' IList' vs' ICollection' vs' Collection'

时间:2012-03-24 21:17:03

标签: c# .net generics collections

我对从公共API方法和属性返回的集合类型感到困惑。

我想到的收藏品是IListICollectionCollection

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

6 个答案:

答案 0 :(得分:126)

ICollection<T>是一个公开集合语义的接口,例如Add()Remove()Count

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

IList<T>本质上是ICollection<T>,具有基于随机订单的访问权限。

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

答案 1 :(得分:67)

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

还将IEnumerable<T>接口视为返回类型。如果结果只是迭代,那么消费者不需要更多。

答案 2 :(得分:53)

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

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

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

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

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


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

答案 3 :(得分:6)

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

IList<T> : ICollection<T>起,ICollection<T>中的所有方法也可在此处实施。

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

Collection<T>IList<T>IListIReadOnlyList<T>提供了实施方案。

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

引用source

  

ICollectionICollection<T>:您想要修改集合或   你关心它的大小。   IListIList<T>:您想修改集合,并且关心集合中元素的排序和/或定位。

答案 4 :(得分:4)

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

如果您之前没有阅读过,Brad Abrams和Krzysztof Cwalina写了一本很棒的书,题为“框架设计指南:可重用.NET库的约定,惯用法和模式”(您可以从{下载摘要) {3}})。

答案 5 :(得分:-5)

有一些主题来自这个问题:

  • 接口与类
  • 哪个特定的类,来自几个相似的类,集合,列表,数组?
  • 普通类与子项(“泛型”)集合

您可能需要强调其面向对象的A.P.I。

接口与类

如果您对界面没有太多经验,我建议坚持上课。 我发现很多时候开发人员都会跳转到接口,即使它不是必需的。

最后,做一个糟糕的界面设计,而不是一个好的类设计, 顺便说一下,最终可以迁移到一个良好的界面设计...

你会在A.P.I.中看到很多接口,但是,不要急于求成, 如果你不需要它。

您最终将学习如何将接口应用于您的代码。

哪个特定类,来自几个相似的类,集合,列表,数组?

c#(dotnet)中有几个类可以互换。如前所述,如果您需要更具体的类,例如“CanBeSortedClass”,那么请在A.P.I中明确表示。

你的A.P.I.用户真的需要知道,你的类可以被排序,或者对元素应用一些格式吗?然后使用“CanBeSortedClass”或“ElementsCanBePaintedClass”, 否则使用“GenericBrandClass”。

否则,请使用更通用的类。

常见的集合类与subitem(“generics”)集合

你会发现有些类包含其他元素, 并且您可以指定所有元素都应该是特定类型。

通用集合是那些可以使用相同集合的类, 对于多个代码应用程序,无需创建新集合, 对于每个新的子项类型,如下所示: Collection

你的A.P.I.用户将需要一个非常特定的类型,所有元素都相同吗?

使用类似List<WashingtonApple>的内容。

你的A.P.I.用户需要几种相关类型吗?

为您的API公开List<Fruit>,并在内部List<Orange>List<Banana>和{{1}使用List<Strawberry> OrangeBanana来自Strawberry的后代。

你的A.P.I.用户是否需要泛型类型集合?

使用Fruit,其中所有项目均为List

干杯。