列表<>容量返回的项目多于添加的项目

Pet*_*ete 13 c# collections list

有几个属性List<T>似乎与列表中的项目数相关 - Capacity,Count(作为属性和方法存在).与Array刚刚 相比,这非常令人困惑Length.

我正在使用,List.Capacity但它给出了意想不到的结果:

List <string> fruits = new List<string>();
fruits.Add("apple");
fruits.Add("orange");
fruits.Add("banana");
fruits.Add("cherry");
fruits.Add("mango");
Console.WriteLine("the List has {0} items in it.", fruits.Capacity);
Run Code Online (Sandbox Code Playgroud)

当我运行此控制台时,控制台显示:

the List has 4 items in it.

我不明白为什么它显示Capacity8,当我只添加5项.

Ada*_*ras 34

Capacity名单代表了多少内存名单目前已经为当前对象预留和对象添加到它.该Count名单是多少项目实际上已经添加到列表中.


M4N*_*M4N 17

以下是MSDN中 Capacity属性的完整说明:


容量是在List<T>需要调整大小之前可以存储的元素数,而Count 是实际在其中的元素数List<T>.

容量始终大于或等于Count.如果Count在添加元素时超出容量,则在复制旧元素和添加新元素之前,通过自动重新分配内部数组来增加容量.

可以通过调用TrimExcess()方法或显式设置Capacity属性来减少容量.显式设置Capacity的值时,还会重新分配内部数组以容纳指定的容量,并复制所有元素.

检索此属性的值是O(1)操作; 设置属性是O(n)操作,其中n是新容量.


Mar*_*ers 8

要添加到其他答案,List逐个添加项时的默认行为是以容量4开始,并在列表变满时将其加倍.这解释了8的容量.


Jul*_*anR 8

为了理解为什么它更大,你需要了解List<T>内部如何工作.在内部,a List<T>使用数组(so T[])来存储其内容.

这个数组以4个元素的大小开始,相当于说T[] array = new T[4].当你向a添加一个项目时List<T>,它存储在数组中:第一个项目array[0],第二array[1]个项目,等等.然而,第五个项目不能适合这个数组,因为它只有四个元素长.并且因为数组的长度在创建后无法更改,所以唯一的选择是获取数组的内容并将其移动到一个新的数组,该数组足以容纳第五个项目.List<T>每次空间用完时,执行选择将数组缓冲区的大小加倍,因此为了适应第五项,它将数组容量加倍为8.然后是16,依此类推.

对于它为什么选择加倍可能有很好的数学支持,它可能是昂贵的复制操作(不想经常分配新缓冲区)和浪费空间之间的良好折衷.通过加倍,内存浪费永远不会超过50%,我相信新阵列需要分配的次数会以对数方式减少.