List <T>上的TrimExcess之后的容量

sla*_*dhe 7 c#

修剪访问用于最小化集合的内存例如

 List<string> myList = new List<string>();
Run Code Online (Sandbox Code Playgroud)

如果我的包含2项后修剪访问容量列表将是2

同样,如果TrimExcess容量分别变为4或5或6,则list包含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;
                }
            }
Run Code Online (Sandbox Code Playgroud)

if语句仅在i = 3时才为真

任何人都可以让我知道原因

dca*_*tro 10

这是源代码List<T>:

  public void TrimExcess() {
        int threshold = (int)(((double)_items.Length) * 0.9);
        if( _size < threshold ) {
            Capacity = _size;
        }
    }
Run Code Online (Sandbox Code Playgroud)

属性_size的支持字段在哪里Count,_items.LengthCapacitygetter返回的内容.

所以基本上,TrimExcess只有Count在没有使用超过10%的阵列插槽时才设置容量.这就是为什么你的一些测试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
Run Code Online (Sandbox Code Playgroud)

为什么第5行打印8? 空列表以0容量开始.

  • 插入第一个元素时,容量增加到4,即其默认容量.
  • 插入第五个元素时,容量增加到当前容量的两倍.因此,如果容量仍为4,则最多为8.
  • 插入第9个元素后,Capacity再次加倍,依此类推.

因此,当您插入第5个元素时,容量从4变为8.如果再插入两个元素,您将看到容量从8到16.

为什么7号线打印8?

我的回答的第一部分已经回答了这个问题.

现在我们知道为什么打电话之前容量是8 TrimExcess.并且因为阵列中未使用的空间*少于10%,TrimExcess所以什么都不做,容量仍为8.

注意:实际上,有12.5%的未使用空间(阵列中有1个空闲插槽/ 8个可能的插槽).但是因为7*0.9被舍入为整数,所以threshold变为7.并且因为7 < 7返回false,所以没有任何反应.