2014-01-03 5 views
1

Если у меня есть список, который я хочу обрезать для сохранения памяти, я, похоже, могу установить емкость списка, а затем ждать, пока GC освободит память. Когда список получает повышение до следующего поколения, выделенная для него память, по-видимому, является функцией емкости списка, а не первоначально выделенной памятью. Это позволяет мне полностью копировать, и в конечном итоге это означает, что всего 1 копия полностью.Могу ли я убедить сборник мусора усечь список? Массив?

var x = new List<double>(50000000) { 1, 2, 3 }; 
//Lots of memory used here 
GC.Collect(2); 
//Still lots of memory used 
x.Capacity = 3; 
GC.Collect(2); 
//Much less memory now used 

Можно ли как-то сделать с массивами?

Обратите внимание, что я не намерен принудительно принудительно использовать GC - это просто для иллюстрации того, что когда GC в конечном итоге происходит, память освобождается.

+0

Нет, вы можете «сжать» это вашей собственной личностью http://stackoverflow.com/questions/12231569/is-there-in-c-sharp-a-method-for-list-like-resize-in-c-for-vectort –

+0

Ну, у VB.NET есть 'ReDim Preserve', но я не нахожусь в компьютер, чтобы использовать Reflector, чтобы подтвердить, как это делается. –

+2

Я думаю, что вы предполагаете, что емкость не копирует внутренний массив на меньший –

ответ

1

Просто используйте TrimExcess из List<T>.

Это эквивалент list.Capacity = list.Count, который выделяет новый массив размером list.Count и копирует все элементы в него.

Вы можете использовать ту же стратегию для массивов, но вы будете иметь код это самостоятельно, хотя:

int[] arr = new int[50000]; 

int count = 3; 
int[] compact = new int[count]; 
Array.Copy(arr, compact, count); 
arr = null; 
+0

ОП спросил о массивах, а не о списках. – Spikeh

+2

Список @Spikeh Well указан в названии, а в коде есть «Список » ... поэтому я не согласен с вашим комментарием. Хотя в этом ответе не хватает многих других деталей. –

+0

@AdamHouldsworth «Можно ли как-то сделать то же самое с массивами?». Это сайт Q & A, и это единственный вопрос здесь ... – Spikeh

1

Боюсь, что нет. Массивы по самой своей природе являются фиксированными.

http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

В частности:

Число измерений, а длина каждой размерности устанавливается при создании экземпляра массива. Эти значения не могут быть изменены за время жизни экземпляра.

Вы сможете освободить память, установив элементы массива на нуль. И, конечно, вы можете изменять размеры массивов вручную, но для этого требуется создать другой массив и скопировать в него соответствующие элементы.

0

Я думаю, что это эквивалентно список вашего примера

var x = new Double[50000000]; 
//Lots of memory used here 
GC.Collect(2); 
//Still lots of memory used 
var y = new Double[3]; 
Array.Copy(x, 0, y, 0, 3); 
x = y; 
GC.Collect(2); 
//Much less memory now used 
1

За кулисами , x.Capacity = 3; или x.TrimExcess() скопирует все записи из частного массива, который их удерживает, до нового крошечного массива. Затем будет собран огромный массив.

Чтобы сделать что-то подобное для собственного массива, вы можете сделать:

var y = new double[50000000]; 
//Lots of memory used here 
GC.Collect(2); 
//Still lots of memory used 

Array.Resize(ref y, 3); 

GC.Collect(2); 
//Much less memory now used 

Doc: Array.Resize<T> method

+0

@Rob Помните, что класс 'List ' имеет поле 'private T [] _items;', которое содержит массив с элементами и, возможно, некоторое дополнительное пространство в массиве. Если вы измените «Емкость», старый экземпляр «_items» будет оставлен, и будет создан новый массив. –

Смежные вопросы