调整List <T>的容量

Chr*_*ris 3 c# algorithm performance memory-management list

System.Collections.Generic.List<T>用Reflector 阅读了.NET4.0 类的源代码,我有一些问题.这是代码:

    [__DynamicallyInvokable]
    public void Add(T item)
    {
        if (this._size == this._items.Length)
        {
            this.EnsureCapacity(this._size + 1);
        }
        this._items[this._size++] = item;
        this._version++;
    }
    private void EnsureCapacity(int min)
    {
        if (this._items.Length < min)
        {
            int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
            if (num > 0x7fefffff)
            {
                num = 0x7fefffff;
            }
            if (num < min)
            {
                num = min;
            }
            this.Capacity = num;
        }
    }
    [__DynamicallyInvokable]
    public int Capacity
    {
        // omitted code

        set
        {
            if (value < this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
            }
            if (value != this._items.Length)
            {
                if (value > 0)
                {
                    T[] destinationArray = new T[value];
                    if (this._size > 0)
                    {
                        Array.Copy(this._items, 0, destinationArray, 0, this._size);
                    }
                    this._items = destinationArray;
                }
                else
                {
                    this._items = List<T>._emptyArray;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)
  • 它是通过将所有元素复制到新数组来调整数组大小的最佳方式还是唯一方法?
  • 为什么用"0x7fefffff"检查"num"?为什么"0x7fefffff"特别?
  • 为什么他们可以直接使用"4"和"0x7fefffff"?他们不是神奇的数字吗?

    谢谢.

Ken*_*rey 5

这是原始源代码(对于.NET 4.0,我相信):

    // Ensures that the capacity of this list is at least the given minimum 
    // value. If the currect capacity of the list is less than min, the
    // capacity is increased to twice the current capacity or to min, 
    // whichever is larger. 
    private void EnsureCapacity(int min) {
        if (_items.Length < min) { 
            int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
            // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
            // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
            if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength; 
            if (newCapacity < min) newCapacity = min;
            Capacity = newCapacity; 
        } 
    }
Run Code Online (Sandbox Code Playgroud)

至于你的问题:

  • 是的,您无法调整现有阵列的大小.但是,Array.Resize允许你做什么List.Capacity,但代码更少.它创建新数组,复制元素,并为您分配新数组.
  • 如果查看原始代码,很明显限制是CLR中数组的大小.看起来数组可以达到int.MaxValue元素长,减去0x100000个插槽,可能是阵列开销.我真的不能说具体的那些插槽是什么.
  • 在原始代码中,它们是常量.C#编译器不编译对常量的引用.它只存储值.这就是常量在反编译代码中成为幻数的原因.