返回“IList”与“ICollection”与“Collection”
我很困惑我应该从我的公共API方法和属性返回哪个集合types。
我脑海中的collections品是IList
, ICollection
和Collection
。
返回这些types之一总是优于其他types,还是取决于具体情况?
一般来说,您应该返回一个尽可能通用的types,即只知道消费者需要使用的返回数据的types。 这样,您可以更自由地更改API的实现,而不会破坏正在使用它的代码。
还要考虑IEnumerable<T>
接口作为返回types。 如果结果只是迭代,消费者不需要更多。
ICollection<T>
是一个暴露集合语义的接口,如Add()
, Remove()
和Count
。
Collection<T>
是ICollection<T>
接口的具体实现。
IList<T>
本质上是一个ICollection<T>
具有随机的基于顺序的访问。
在这种情况下,您应该决定您的结果是否需要列表语义,如基于命令的索引(然后使用IList<T>
),或者您是否需要返回无序的“bag”结果(然后使用ICollection<T>
)。
IList<T>
和ICollection<T>
之间的主要区别在于IList<T>
IList<T>
允许您通过索引访问元素。 IList<T>
描述了类似数组的types。 ICollection<T>
中的元素只能通过枚举访问。 两者都允许插入和删除元素。
如果您只需要枚举集合,那么使用IEnumerable<T>
是首选。 它有两个优点:
-
它禁止更改集合(但不包括引用的对象,如果元素是引用)。
-
它允许尽可能多的来源,包括algorithm生成的枚举,而不是集合。
Collection<T>
是一个基本类,主要用于集合的实现者。 如果你在接口(APIs)中公开它,那么许多有用的集合将被排除在外。
IList<T>
一个缺点是数组实现它,但不允许你添加或删除项目(即你不能改变数组的长度)。 如果在数组上调用IList<T>.Add(item)
,将抛出exception。 由于IList<T>
具有一个布尔属性IsReadOnly
,您可以在尝试这样做之前检查这种情况。 但在我看来,这仍然是图书馆的devise缺陷 。 因此,当需要添加或移除项目的可能性时,我直接使用List<T>
。
IList<T>
是所有通用列表的基本接口。 由于它是一个有序的集合,所以实现可以决定sorting顺序,从sorting顺序到sorting顺序。 此外, Ilist
Item属性允许方法根据索引读取和编辑列表中的条目。 这使得可以在位置索引处插入/从列表中删除值。
另外,由于IList<T> : ICollection<T>
, IList<T> : ICollection<T>
中的所有方法也可在此处实现。
ICollection<T>
是所有generics集合的基本接口。 它定义了大小,枚举器和同步方法。 您可以添加或删除一个项目到一个集合中,但是由于没有索引属性,您不能select在哪个位置发生。
Collection<T>
为IList<T>
, IList
和IReadOnlyList<T>
提供了一个实现。
如果使用较窄的接口types(例如ICollection<T>
而不是IList<T>
,则可以保护代码免受重大更改的影响。 如果使用更宽的接口types(如IList<T>
,则更有可能破坏代码更改。
引用来源 ,
ICollection
,ICollection<T>
:您想要修改集合或关心其大小。IList
,IList<T>
:您想要修改集合,并关心集合中元素的sorting和/或位置。
返回一个接口types更一般,所以(缺乏关于你的具体用例的进一步的信息)我会倾向于这个。 如果要公开索引支持,请selectIList<T>
,否则ICollection<T>
就足够了。 最后,如果要指示返回的types是只读的,请selectIEnumerable<T>
。
而且,如果您还没有阅读过,Brad Abrams和Krzysztof Cwalina写了一本名为“Framework Design Guidelines:Conventions,Idioms,and Patterns for Reusable .NET Libraries”的书(可以从这里下载摘要)。
有一些问题来自这个问题:
- 接口与类
- 哪些具体的类,从几个相似的类,集合,列表,数组?
- 普通类与子类(“generics”)集合
您可能需要强调其面向对象的API
接口与类
如果你没有太多接口的经验,我build议坚持上课。 我看到很多开发人员跳入界面,即使它不是必需的。
而且,最终做的糟糕的界面devise,而不是一个好的类devise,顺便说一句,最终可以迁移到一个良好的界面devise…
你会在API中看到很多接口,但是,如果你不需要的话,不要急于接受它。
您最终将学习如何将接口应用于您的代码。
哪些具体的类,从几个相似的类,集合,列表,数组?
c#(dotnet)中有几个类可以互换。 如前所述,如果您需要更具体的类(如“CanBeSortedClass”),请在API中明确指定。
你的API用户是否真的需要知道,你的类可以被sorting,或者对这些元素应用某种格式? 然后使用“CanBeSortedClass”或“ElementsCanBePaintedClass”,否则使用“GenericBrandClass”。
否则,使用更普通的类。
通用集合类与子类(“generics”)集合
您会发现有些类包含其他元素,您可以指定所有元素应该是特定的types。
generics集合是那些可以使用相同集合的类,对于多个代码应用程序,无需为每个新子types创build新集合,如下所示: Collection 。
你的API用户是否需要一个非常特定的types,对于所有的元素都是一样的?
使用像List<WashingtonApple>
东西。
你的API用户是否需要几种相关的types?
公开List<Fruit>
为您的API,并使用List<Orange>
List<Banana>
, List<Strawberry>
内部,其中Orange
, Banana
和Strawberry
是Fruit
后代。
你的API用户是否需要一个genericstypes集合?
使用List
,其中所有项目都是object
。
干杯。