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();
以下是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将决定何时收集。。。