C#列表<;字符串>;内存未收集

本文关键字:内存 字符串 列表 lt gt | 更新日期: 2023-09-27 18:26:26

此代码分配内存,但从不释放内存。如何强制收集内存,GC.Collect()似乎也不起作用。

我看过很多问这个问题的帖子,但每个人都回答说垃圾收集器会处理内存,但它从来没有。

    var list = new List<string>();
    for (var i = 0; i < 10000000; i++)
    {
      list.Add("really long string..................................................................................................");
    }
    for (var i = 0; i < 10000000; i++)
    {
      list[i] = null;
    }
    list.Clear();

C#列表<;字符串>;内存未收集

以下是List<T>.Clear:的代码

// Clears the contents of List.
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++;
}

正如您所看到的,数组保持原样分配。这样做是出于效率的原因。数组已经分配好了,没有必要让GC收集它,因为它可能会再次被需要。

您可以设置Capacity属性以强制其重新分配新阵列。这实际上会增加内存压力(除非将其设置为0),直到收集到上一个数组为止。这是供参考的代码:

// Gets and sets the capacity of this list.  The capacity is the size of
// the internal array used to hold items.  When set, the internal 
// array of the list is reallocated to the given capacity.
// 
public int Capacity {
    get {
        Contract.Ensures(Contract.Result<int>() >= 0);
        return _items.Length;
    }
    set {
        if (value < _size) {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        }
        Contract.EndContractBlock();
        if (value != _items.Length) {
            if (value > 0) {
                T[] newItems = new T[value];
                if (_size > 0) {
                    Array.Copy(_items, 0, newItems, 0, _size);
                }
                _items = newItems;
            }
            else {
                _items = _emptyArray;
            }
        }
    }
}

至于真正长的字符串,它只是对一个内部字符串的引用。。。无论如何,该列表将为每个项目存储8个字节(假设是64位系统)。

如果显式调用GC.Collect(),并不意味着它将立即被收集。GC将决定何时收集。。。