如果删除元素,列表<T>将缩小大小

Ale*_*ide 22 c# list

当a List<T>变满时,它的大小增加一倍,占用内存的两倍,但如果从中删除元素,它会自动减小吗?

据我所知,减少Capacity并不意味着重新定位内存中的所有数据,它只需要从保留内存的末尾删除,但它实际上是否会这样做?

Ser*_*rvy 27

不,List除非您通过设置该属性或使用显式降低容量,否则不会降低容量,除非TrimExcess您调用Clear它并且它可以完全删除缓冲区.

当然,这只是当前的实现,它是一个实现细节,所以你不能依赖它而不缩小后备阵列.


Joe*_*orn 8

不,List<T>不会自动回收任何作为目前实施的空间,这是不太可能实施这一项目很快改变.

但那只是故事的一部分.请记住,一般来说,List<T>只存储对您商品的引用.如果您有一个包含许多对象的大型列表,并且您删除了其中一半,以便不再使用已删除的对象,那么当GC收集这些对象时,将会回收非常接近列表一半内存的内容 .

另外,我的理解是当前的实现将压缩剩余的项目,这样当列表再次增长时,它会重新使用为内部列表使用的当前数组分配的内存中的点.

最后,有办法手动回收空间......但要谨慎使用它们.大多数时候,GC最了解.调用TrimExcess()是因为您刚刚从大型列表中删除了少量项目,这通常是您的应用程序的净损失.


Swe*_*per 7

参考源,我们可以看到该Remove方法调用RemoveAt方法,该方法实现如下:

public void RemoveAt(int index) {
    if ((uint)index >= (uint)_size) {
        ThrowHelper.ThrowArgumentOutOfRangeException();
    }
    Contract.EndContractBlock();
    _size--;
    if (index < _size) {
        Array.Copy(_items, index + 1, _items, index, _size - index);
    }
    _items[_size] = default(T);
    _version++;
}
Run Code Online (Sandbox Code Playgroud)

似乎没有任何调整基础数组的大小_items.它仅将索引处的项设置为默认值.

基本上没有.

另请注意,该Clear方法也不会调整数组的大小.它调用Array.Clear将基础数组中的所有项设置为默认值.

public void Clear() {
    if (_size > 0)
    {
        Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
        _size = 0;
    }
    _version++;
}
Run Code Online (Sandbox Code Playgroud)