System.Collections.ObjectModel.Collection <t>的“Add”方法如何工作?</t>

时间:2012-06-01 15:54:50

标签: c# .net c#-4.0

背景:我正在尝试创建自己的“Vector”类,以帮助对数字组执行数学计算。我正在重载算术运算符(+ - * /)以实现我想要的功能。起初,我在我的类中使用了一个私有数组,然后实现了IEnumerable<T>接口。之后,我想继承List<T>类,但在阅读了几篇文章后,我明白我应该使用Collection<T>。请注意,在使用数据填充“Vector”对象时,性能非常重要

问题Collection<T>.Add()方法如何运作? List<T>.Add() documentation非常明确:

  

如果Count已经等于Capacity,则通过自动重新分配内部数组来增加List的容量,并在添加新元素之前将现有元素复制到新数组。

但是,Collection<T>.Add() documentation对其工作原理一无所知。当我使用List<T>作为我的基类时,我可以访问Capacity属性,并且在使用Add()方法之前我能够指定大小。但是,Collection<T>没有Capacity属性 - 这就是我提出这个问题的原因。我再次重申:表现非常重要。

由于性能是个问题,或许我应该回到使用私有数组并实现IEnumerable<T>接口。你觉得怎么样?

2 个答案:

答案 0 :(得分:4)

Collection<T>IList<T>的包装。 Collection<T>的默认构造函数只使用新的List<T>,因此假设您使用默认构造函数,Add行为将与List<T>相同。

  

但是,Collection.Add()文档根本没有说明它是如何工作的

那是因为Add行为取决于底层IList,它在构造函数中传递。

  

但是,Collection没有Capacity属性

同样,因为这取决于Collection包装的内容。它包装接口 IList<T>。该接口没有容量概念。 可以IList<T>的实现,它没有已知的容量,比如数据库中的记录。

如果您需要这些实施细节,例如容量,那么只需使用List<T>Collection<T>List<T>相比没有任何性能优势,因为无论如何它都使用了{{1}}。如果性能对您至关重要,那么您可能希望找到一个已经解决了这个问题的库,而不是自己编译。

答案 1 :(得分:2)

没有关于实现的详细信息,但文档中有Add的性能特征:

List<T>.Add

  

如果Count小于Capacity,则此方法为O(1)操作。如果需要增加容量以容纳新元素,则此方法将成为O(n)操作,其中n为Count。

Collection<T>.Add(截至2012-06-01)

  

此方法是O(1)操作。

请注意,Collection<T>.Add的保证看起来不适合至少在List<T>上创建为包装的集合,或者使用Collection的默认构造函数(实现为Collection()):this(new List() )正如@vcsjones指出的那样。看起来像文档中的错误。

通过测量(这是解决性能问题的正确方法)或嗅探来源应该很容易验证......

旁注:你不能用单个数组击败List的Add性能(因为它正是List所做的),你需要使用更复杂的东西(比如数据块列表)来得到O(1 )来自Add和Item []。