集合类及其使用

我遇到了以下代码:

var collection = new Collection(); 

我没有看到Collection类使用太多,也找不到太多关于它的用途的信息。 查看.NET Framework源代码,它几乎只是List的包装器,因为它存储了List成员字段。 它的构造函数如下:

 public Collection() { this.items = (IList) new List(); } 

它还实现了IList。 所以你可以将Collection声明为:

 IList collection = new Collection(); 

对我来说,在function上等同于创建一个List:

 IList collection = new List(); 

那么你什么时候想在自己的代码中使用它? 我看到它是其他.NET集合的基类,但为什么它们将它作为公共具体 (而不是内部和/或抽象)包含在内?


关于可能重复的注释 – 相关问题的答案似乎表明Collection类应该用作基类。 我真正要求的不同之处在于:

  1. 如果在您自己的代码中使用,为什么不使用List作为基类呢?
  2. 在您自己的代码中实例化一个新的集合代替List真的有意义吗?
  3. 如果真的只是作为基类提供, 为什么它不是抽象的

我认为MSDN文档本身已经列出了最重要的方面(由我强调):

Collection类提供受保护的方法 ,可用于在添加和删除项目,清除集合或设置现有项目的值时自定义其行为

对实施者的说明

提供此基类是为了使实现者更容易创建自定义集合。 鼓励实施者扩展此基类,而不是创建自己的基类。

[编辑ypur更新问题]

1.如果在您自己的代码中使用,为什么不使用List作为基类呢?

Collection提供了一些受保护的方法,因此您可以轻松override行为并完全注册您自己的业务逻辑,例如:

  • ClearItems()
  • InsertItem()
  • RemoveItem()
  • SetItem()

List不提供它们,并且几乎没有用于覆盖行为的受保护方法,这使得自定义更难。

2.在您自己的代码中使用List初始化新集合是否真的有意义?

不,不只是为了初始化一些集合。 如果您需要它作为实现自己的逻辑的基类,请使用它。

这取决于您自己的业务需求。 对于日常开发工作中的几乎所有情况,现有的和众多的集合应该已经提供了您所需要的。 有类型安全和无类型集合,线程安全集合,以及您能想到的任何其他内容。

尽管如此,有一天可能需要实现一种集合类型,该集合类型在允许添加/更新/删除其中的任何项目之前执行某些validation检查,或者以特定的方式处理移动到仅在稀疏填充的列表中的下一个项目。 你永远不知道顾客可能有什么想法。

在这种情况下,创建自己的集合类型可能会有所帮助。

Collection(T)类是一大堆其他集合类的基类。 List类是针对速度进行了优化的类,而Collection类是为可扩展性而设计的。

当您查看Collection(T)的成员时,您将看到它包含List(T)类没有的一些其他受保护的虚拟方法(如InsertItem )。

实际上,我已经创建了Collection类的一个实例。 我想我只会将此类型用作方法签名中的参数,只是为了不将该方法与集合的实现紧密耦合(如果可能)。

回答你的问题:

  1. 我会使用Collection(T)作为基类,因为该类的目的是用作其他集合类型的基类。 它为您提供了更大的灵活性(请参阅受保护的虚拟方法InsertItemRemoveItemSetItem

  2. 当需要集合时,我将使用List(T)类的实例,因为它针对速度进行了优化。

  3. 实际上,我想知道为什么他们没有将Collection(T)类抽象化。

正如Krzysztof Cwalina 所说 :

•列表不是为了扩展而设计的。 即你不能覆盖任何成员。 例如,这意味着在修改集合时,无法通知从属性返回List的对象。 通过集合,您可以覆盖SetItem受保护的成员,以便在添加新项目或更改现有项目时获得“通知”。

•列表中有许多成员在许多情况下都不相关。 我们说List对于公共对象模型来说太“忙”了。 想象一下ListView.Items属性返回List的所有丰富性。 现在,看看实际的ListView.Items返回类型; 它更简单,类似于Collection或ReadOnlyCollection。

因此,FxCop的规则CA1002也告诉您不要公开通用列表并改为使用Collection。 另请参阅此代码分析团队博客文章,了解有关FxCop规则以及返回Collection而不是List的原因。

因此,对于问题1和2,请参见上文。 至于问题三,它不仅仅是作为一个基类。 你应该能够实例化它并将其用作返回类型,因此它不是抽象的。

我真的不喜欢回答我自己的问题,但就第三季而言,我相信我理解这个推理。 我看到Bas Paap回答中提到的这个链接时得到了它。

简而言之,Collection类不是抽象的原因是因为您可能希望自己选择在以后从类派生。 在此期间,您可以将其用作返回类型并直接实例化它。 该链接显示了一个代码示例,其中就是这种情况。

我已经提出了我认为解决问题中提出的问题的所有其他答案。

尽管枚举接口提供了对集合的仅向前迭代,但它们不提供确定集合大小,通过索引访问成员,搜索或修改集合的机制。 对于此类function,框架提供ICollectionIListIDictionary接口。

ICollection提供中等function(例如Count属性)。

IList及其非generics版本提供最大function(包括索引的“随机”访问)。

您很少需要实现任何这些接口。 几乎在所有情况下,当您需要编写集合类时,您可以改为inheritanceCollection等。

我希望这有帮助。