我对于应该从公共API方法和属性返回哪种集合类型感到困惑。
我心目中的集合是IList,ICollection和Collection。
返回这些类型中的一种总是总是比其他类型更受青睐,还是取决于特定情况?
我对于应该从公共API方法和属性返回哪种集合类型感到困惑。
我心目中的集合是IList,ICollection和Collection。
返回这些类型中的一种总是总是比其他类型更受青睐,还是取决于特定情况?
Answers:
通常,您应该返回一种尽可能通用的类型,即,该类型仅知道使用者需要使用的返回数据。这样,您就拥有更大的自由来更改API的实现,而无需破坏正在使用它的代码。
还可以将IEnumerable<T>接口视为返回类型。如果结果只是要迭代,那么消费者就不需要更多了。
Count方法的实现会检查集合的实际类型,因此它将对某些已知类型(例如数组)使用Length或Count属性,ICollection甚至当您将其作为提供时也是如此IEnumerable。
Thing<T>实现IList<T>而不是非泛型ICollection,则调用IEnumerable<Cat>.Count()a Thing<Cat>会很快,但是调用IEnumerable<Animal>.Count()会很慢(因为扩展方法将查找而不是找到的实现)ICollection<Cat>)。如果该类实现了非泛型ICollection,IEnumerable<Animal>.Count则会找到并使用它。
ICollection<T>是暴露集合语义诸如接口Add(),Remove()和Count。
Collection<T>是该ICollection<T>接口的具体实现。
IList<T>本质上是ICollection<T>基于随机订单的访问。
在这种情况下,您应该决定结果是否需要列表语义,例如基于订单的索引(然后使用IList<T>),或者是否只需要返回无序的结果“袋”(然后使用ICollection<T>)。
Collection<T>实现IList<T>不仅ICollection<T>。
IEnumerable<T>是有序的。有什么区别IList<T>的ICollection<T>是,它为会员提供与索引工作。例如list[5]可行,但collection[5]不会编译。
IList<T>。有很多没有的有序集合。IList<T>关于快速索引访问。
IEnumerable<T>已订购所有收藏品,因为已订购?拿HashSet<T>-它实现了,IEnumerable<T>但显然没有命令。也就是说,您对项目的顺序没有任何影响,并且如果内部哈希表已重新组织,则此顺序可以随时更改。
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>当需要添加或删除项目时,我直接使用。
IList<T>,则无法确保不会将数组作为参数调用该方法。
IList<T>是所有通用列表的基本接口。由于它是有序集合,因此实现可以决定排序,范围从排序的顺序到插入顺序。而且Ilist具有Item属性,该属性允许方法根据索引来读取和编辑列表中的条目。这样就可以在位置索引处从列表中插入值或从列表中删除值。
此外,由于IList<T> : ICollection<T>,ICollection<T>此处的所有方法也都可用于实现。
ICollection<T>是所有通用集合的基本接口。它定义了大小,枚举器和同步方法。您可以将项目添加或删除到集合中,但是由于缺少index属性,您无法选择它发生在哪个位置。
Collection<T>提供了一个实现IList<T>,IList和IReadOnlyList<T>。
如果您使用较窄的接口类型,例如 ICollection<T>而不是的IList<T>,则可以保护您的代码以防破坏更改。如果使用更广泛的接口类型(例如)IList<T>,则更有可能破坏代码更改。
从来源报价,
ICollection,ICollection<T>:你想修改的集合或者你关心它的大小。IList,IList<T>:你想修改的收集和你关心的集合中的元素的顺序和/或定位。
返回接口类型更为通用,因此(在您的特定用例上缺少更多信息)我倾向于这样做。如果要提供索引支持,请选择IList<T>,否则ICollection<T>就足够了。最后,如果要指示返回的类型为只读,请选择IEnumerable<T>。
而且,如果您以前从未读过它,Brad Abrams和Krzysztof Cwalina写了一本很棒的书,标题为“框架设计准则:可重用.NET库的约定,惯用语和模式”(您可以从此处下载摘要)。
IEnumerable<T>是只读的?可以,但是即使在执行ToList之后在存储库的上下文中对其进行重新调整也不是线程安全的。问题是原始数据源获取GC时,IEnumarble.ToList()在多线程上下文中不起作用。它工作于线性状态,因为在您完成工作后会调用GC,但async现在在4.5+的版本中使用IEnumarbale变得越来越痛苦。
这个问题有一些主题:
您可能要强调它是一个面向对象的API
接口与类
如果您对接口没有太多经验,我建议您坚持使用类。我看到很多时候开发人员都跳到了接口,即使它不是必须的。
而且,最终要做一个糟糕的界面设计,而不是一个好的类设计,顺便说一句,最终可以将其移植到一个好的界面设计中。
您会在API中看到很多接口,但是,如果您不需要它,请不要着急。
您最终将学习如何将接口应用于代码。
从几个相似的类,集合,列表,数组中,哪个特定的类?
c#(dotnet)中有几个可以互换的类。如前所述,如果您需要更具体的类中的内容(例如“ CanBeSortedClass”),请在您的API中明确显示。
您的API用户是否真的需要知道,您的类可以排序,还是将某些格式应用于元素?然后使用“ CanBeSortedClass”或“ ElementsCanBePaintedClass”,否则使用“ GenericBrandClass”。
否则,请使用更通用的类。
通用集合类与子项(“泛型”)集合
您会发现有些类包含其他元素,并且可以指定所有元素应为特定类型。
泛型集合是可以为多个代码应用程序使用相同集合的类,而不必为每个新的子项目类型创建新集合,例如:Collection。
您的API用户是否需要一个非常特定的类型,所有元素都一样?
使用类似的东西List<WashingtonApple>。
您的API用户是否需要几种相关类型?
暴露List<Fruit>你的API,并使用List<Orange> List<Banana>,List<Strawberry>在内部,在那里Orange,Banana并Strawberry从后代Fruit。
您的API用户是否需要泛型类型集合?
使用List,其中所有项目均为object。
干杯。