我遇到了以下代码:
var collection = new Collection<string>();
我没有看到Collection类使用太多,也找不到太多关于它的用途的信息。查看.NET Framework源代码,它几乎只是List的包装器,因为它存储了List成员字段。它的构造函数如下:
public Collection()
{
this.items = (IList<T>) new List<T>();
}
它还实现了IList。因此,您可以将Collection声明为:
IList<string> collection = new Collection<string>();
对我来说,在功能上等同于创建一个List:
IList<string> collection = new List<string>();
那么您何时想在自己的代码中使用List?我看到它是其他.NET集合的基类,但为什么它们将它包含为公共具体(而不是内部和/或抽象)?
关于可能重复的评论 - 相关问题的答案似乎表明Collection类应该用作基类。我真正要求的是:
答案 0 :(得分:17)
我认为MSDN documentation本身已经列出了最重要的方面(由我强调):
Collection类提供可以使用到的受保护方法 添加和删除项目时,自定义其行为,清除 收集或设置现有项目的价值。
和
对实施者的说明
提供此基类是为了使实施者更容易 创建自定义集合。 鼓励实施者扩展这一点 基类而不是创建自己的。
[编辑ypur更新问题]
1。如果在您自己的代码中使用,为什么不使用List作为基类?
Collection<T>
提供了一些受保护的方法,因此您可以轻松地override
行为并完全注册您自己的业务逻辑,例如:
ClearItems()
InsertItem()
RemoveItem()
SetItem()
List<T>
没有提供它们,并且几乎没有任何受保护的方法来覆盖行为,这使得自定义更加困难。
2。在您自己的代码中使用List初始化新集合是否真的有意义?
不,不只是为了初始化一些集合。如果您需要它,请使用它作为实现您自己的逻辑的基类。
这取决于您自己的业务需求。对于日常开发工作中的几乎所有情况,现有的和众多的集合应该已经提供了您所需要的。有类型安全和无类型集合,线程安全集合,以及您能想到的任何其他内容。
仍然有一天,可能需要实现一个集合类型,它执行某些验证检查,然后才允许添加/更新/删除其中的任何项目,或者处理移动到仅在稀疏填充的列表中的下一个项目一种特殊的方式。你永远不知道顾客可能有什么想法。
在这种情况下,创建自己的集合类型可能会有所帮助。
答案 1 :(得分:9)
Collection(T)类是一大堆其他集合类的基类。 List类是针对速度进行优化的类,而Collection类是为可扩展性而设计的。
当您查看Collection(T)
的成员时,您会看到它包含List(T)
类没有的其他一些受保护的虚拟方法(如InsertItem
)。 / p>
实际上,我已经创建了Collection类的一个实例。我想我只会将此类型用作方法签名中的参数,只是为了不将方法与集合的实现紧密结合(如果可能)。
回答你的问题:
我会使用Collection(T)
作为基类,因为它是
该类的意图被用作其他类的基类
集合类型。它为您提供更大的灵活性(请参阅受保护的
虚方法InsertItem
,RemoveItem
和SetItem
)
当需要集合时,我会使用一个实例
List(T)
类,因为它针对速度进行了优化。
实际上,我想知道为什么他们没有制作Collection(T)
课堂摘要。
答案 2 :(得分:7)
作为Krzysztof Cwalina puts it:
•列表不是为了扩展而设计的。即你不能覆盖任何成员。例如,这意味着在修改集合时,无法通知从属性返回List的对象。 Collection允许您覆盖SetItem受保护的成员,以便在添加新项目或更改现有项目时获得“通知”。
•列表中有许多成员在许多场景中都不相关。我们说List对于公共对象模型来说太“忙”了。想象一下ListView.Items属性返回List的所有丰富性。现在,看看实际的ListView.Items返回类型;它更简单,类似于Collection或ReadOnlyCollection。
出于这个原因,FxCop的规则CA1002也告诉您不要公开通用列表并改为使用Collection。另请参阅此Code Analysis Team Blog post有关FxCop规则以及返回Collection而不是List的原因。
因此对于问题1和2,请参见上文。至于问题三,它不仅仅是作为一个基类。您应该能够实例化它并将其用作返回类型,因此它不是抽象的。
答案 3 :(得分:4)
我真的不喜欢回答我自己的问题,但就第3季而言,我相信我理解这个推理。我在看看Bas Paap的回答中提到的this link时得到了它。
简而言之,Collection类不是抽象的原因是因为您可能希望自己选择以后从类中派生。在此期间,您可以将其用作返回类型并直接实例化它。 The link显示了一个代码示例,其中就是这种情况。
我已经提出了我认为解决问题中提出的问题的所有其他答案。
答案 4 :(得分:0)
尽管枚举接口提供了对集合的仅向前迭代,但它们不提供确定集合大小,通过索引访问成员,搜索或修改集合的机制。对于此类功能,框架提供ICollection
,IList
和IDictionary
接口。
ICollection<T>
提供中等功能(例如Count
属性)。
IList<T>
及其非通用版本提供了最大功能(包括索引的“随机”访问)。
您很少需要实施这些接口。几乎在所有情况下,当您需要编写集合类时,您可以改为继承Collection<T>
等。
我希望这会有所帮助。