我对从公共API方法和属性返回的集合类型感到困惑。
我想到的收藏品是IList
,ICollection
和Collection
。
返回其中一种类型总是优先于其他类型,还是取决于具体情况?
答案 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>
将是首选。它有两个优点:
它不允许更改集合(但不允许更改为引用的对象,如果它们是引用类型)。
它允许尽可能多种来源,包括通过算法生成的枚举,而不是集合。
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>
,IList
和IReadOnlyList<T>
提供了实施方案。
如果您使用较窄的界面类型(例如ICollection<T>
而不是IList<T>
),则可以保护代码免受更改。如果使用更宽的接口类型(如IList<T>
),则更容易破坏代码更改。
引用source,
ICollection
,ICollection<T>
:您想要修改集合或 你关心它的大小。IList
,IList<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>
Orange
,Banana
来自Strawberry
的后代。
你的A.P.I.用户是否需要泛型类型集合?
使用Fruit
,其中所有项目均为List
。
干杯。