修剪访问用于最小化集合的内存 例如
List<string> myList = new List<string>();
如果我在列表的修剪访问能力之后包含2个项目将是2
如果TrimExcess容量分别变为4或5或6,则列表包含4或5或6
但如果列表包含3或7或15,为什么在TrimExcess之后容量分别变为4或8或16
即使在此之后我发现了一个更奇怪的行为 如果我运行以下代码
List<int> myList = new List<int>();
for (int i = 1; i <= 100; i++)
{
myList.Add(1);
myList.TrimExcess();
if (myList.Capacity != myList.Count())
{
var different = myList.Capacity;
}
}
if语句仅在i = 3
时才为真任何人都可以让我知道原因
答案 0 :(得分:10)
以下是List<T>
的源代码:
public void TrimExcess() {
int threshold = (int)(((double)_items.Length) * 0.9);
if( _size < threshold ) {
Capacity = _size;
}
}
其中_size
是Count
属性的支持字段,而_items.Length
是Capacity
获取者返回的内容。
基本上,如果没有使用超过10%的阵列插槽,TrimExcess
仅将容量设置为Count
。这就是为什么在某些测试中Count
不等于Capacity
。
评论中的另一个问题:
1 List<int> myList = new List<int>
2 {
3 1,2,3,4,5,6,7 // equivalent to calling `Add` 7 times
4 };
5 Console.WriteLine(myList.Capacity); // prints 8
6 myList.TrimExcess();
7 Console.WriteLine(myList.Capacity); // prints 8
为什么第5行打印8? 空列表以0容量开始。
因此,当您插入第5个元素时,容量从4变为8.如果再插入两个元素,您将看到容量从8到16。
为什么第7行打印8?
我的答案的第一部分已经回答了这个问题。
现在我们知道为什么在调用TrimExcess
之前容量为8 。
并且因为阵列中未使用的空间*少于10%,TrimExcess
什么也不做,容量仍为8。
注意:实际上,有12.5%的未使用空间(阵列中有1个空闲插槽/ 8个可能的插槽)。
但是因为7 * 0.9四舍五入为整数,threshold
变为7.并且因为7 < 7
返回false,所以没有任何反应。
答案 1 :(得分:2)
取自msdn-Documentation on List.TrimExcess:
重新分配和复制大型列表的成本可能相当大,因此,如果列表的容量超过容量的90%,则TrimExcess方法不会做任何事情。这样可以避免因相对较小的收益而产生大量的重新分配成本。
这意味着,在大多数情况下,List.TrimExcess()调用不执行任何操作,因此List.Count和List.Capacity之间存在差异
答案 2 :(得分:1)
我不知道原因,但我决定找出:
public void TrimExcess()
{
int num = (int) (this._items.Length * 0.9);
if (this._size < num)
{
this.Capacity = this._size;
}
}
这对我来说很惊讶。如果浪费的空间超过10%,它只会削减集合的容量。看起来像是对常见情况的聪明优化(开发人员在不应该......时调用TrimExcess
。)。
修剪自己:
list.Capacity = list.Size;