List<T>
上有几个属性似乎与列表中的项目数相关 - Capacity
,Count
(作为属性和方法存在)。与仅有Array
的{{1}}相比,这非常令人困惑。
我正在使用Length
,但它会产生意想不到的结果:
List.Capacity
当我运行此控制台时,控制台显示:
the List has 4 items in it.
我不明白为什么它显示{8}的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);
,当我只添加了5项时。
答案 0 :(得分:32)
列表的Capacity
表示列表当前为当前对象和要添加到其中的对象留出的内存量。列表的Count
是实际添加到列表中的项目数。
答案 1 :(得分:16)
以下是Capacity属性from MSDN的完整说明:
容量是List<T>
在调整大小之前可以存储的元素数量,而计数是{{>>中实际存在的元素数量{1}}。
容量始终大于或等于Count。如果在添加元素时Count超过Capacity,则在复制旧元素和添加新元素之前自动重新分配内部数组会增加容量。
可以通过调用TrimExcess()方法或显式设置Capacity属性来减少容量。当显式设置Capacity的值时,也会重新分配内部数组以容纳指定的容量,并复制所有元素。
检索此属性的值是O(1)操作;设置属性是一个O(n)操作,其中n是新容量。
答案 2 :(得分:8)
要添加到其他答案,逐个添加项目时List的默认行为是以容量4开始,并在列表变满时将其加倍。这解释了8的容量。
答案 3 :(得分:8)
为了理解为什么它更大,你需要了解List<T>
内部如何运作。在内部,List<T>
使用数组(所以T[]
)来存储其内容。
这个数组以4个元素的大小开始,相当于说T[] array = new T[4]
。当您将项目添加到List<T>
时,它会存储在数组中:array[0]
中的第一项,array[1]
中的第二项,等等。但是,第五项不能适合这个数组,因为它只有四个元素。并且因为数组的长度在创建后无法更改,所以唯一的选择是获取数组的内容并将其移动到 new 数组,该数组足够大以容纳该数组。第五项也是。 List<T>
的实现选择每次空间用完时将数组缓冲区的大小加倍,因此为了适应第五项,它将数组容量加倍为8.然后是16,依此类推。
为什么它选择加倍可能有很好的数学支持,这可能是昂贵的复制操作(不想经常分配新缓冲区)和浪费空间之间的良好折衷。通过加倍,内存浪费永远不会超过50%,我相信新阵列需要分配的次数会以对数方式减少。
答案 4 :(得分:0)
容量与列表的项目数不同。默认情况下,所有语言中实现良好的列表容器分配的内存超过了保存当前条目数所需的内存。这是因为在某些时候分配更大的内存块比在每次添加内存时为另外一个项目分配内存更有效。