Хотите знать, как сохранить память в C #, используя List <> со структурами? - PullRequest
3 голосов
/ 23 марта 2010

Я даже не уверен, как мне сформулировать этот вопрос. Я передаю некоторые объекты CustomStruct в качестве параметров методу класса и сохраняю их в списке. Мне интересно, возможно ли и более эффективно добавить несколько ссылок на конкретный экземпляр CustomStruct, если найден эквивалентный экземпляр.

Это фиктивная / примерная структура:

public struct CustomStruct
{
    readonly int _x;
    readonly int _y;
    readonly int _w;
    readonly int _h;
    readonly Enum _e;
}

Используя приведенный ниже метод, вы можете передать один, два или три объекта CustomStruct в качестве параметров. В последнем методе (который принимает три параметра) может быть так, что 3-й и, возможно, 2-й будут иметь то же значение, что и первый.

List<CustomStruct> _list;

public void AddBackground(CustomStruct normal)
{
    AddBackground(normal, normal, normal);
}

public void AddBackground(CustomStruct normal, CustomStruct hover)
{
    AddBackground(normal, hover, hover);
}

public void AddBackground(CustomStruct normal, CustomStruct hover, CustomStruct active)
{
    _list = new List<CustomStruct>(3);
    _list.Add(normal);
    _list.Add(hover);
    _list.Add(active);
}

Поскольку метод стоит сейчас, я считаю, что он создаст новые экземпляры объектов CustomStruct, а затем добавит ссылку на каждый из них в список.

Насколько я понимаю, если я вместо этого проверю на равенство между normal и hover и (если равен) вставьте normal снова вместо hover , когда метод завершится, hover потеряет все ссылки и в конечном итоге будет собирать мусор, тогда как normal будет иметь две ссылки в списке. То же самое можно сделать для active .

Это было бы лучше, верно? CustomStruct является ValueType, и поэтому один экземпляр останется в стеке, а три ссылки на List будут просто указывать на него. Общий размер списка определяется не типом объекта, а его емкостью. Удаляя «дубликаты» объектов CustomStuct, вы разрешаете их очищать.

Когда объекты CustomStruct передаются этим методам, новые экземпляры создаются каждый раз. Когда структуры добавляются в список, создается ли еще одна копия? Например, если я передаю только один CustomStruct, AddBackground (normal) создает копию исходной переменной и затем передает ее три раза в Addbackground (normal, hover, active). В этом методе три копии сделаны из оригинальной копии. Когда три локальные переменные добавляются в список с помощью Add (), создаются ли дополнительные копии внутри Add (), и это противоречит цели любых проверок на равенство, как упоминалось ранее?

Есть ли лучший способ справиться с этим? Должны ли структуры передаваться как ссылки на методы, чтобы обойти это?

Я что-то здесь упускаю?

Ответы [ 3 ]

2 голосов
/ 23 марта 2010

Вы говорите о сборке мусора и структурах в одной строке, что не имеет смысла.В конечном счете, каждый раз, когда вы просматриваете структуру, она может копировать себя.Если вы хотите повторно использовать ту же ссылку, то вам нужен либо класс, либо вам нужно обернуть структуру в класс (бокс; встроенный или ручной).

Чтофактически происходит в вашем коде:

_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(hover); // a **copy** of hover is set into the list
_list.Add(active); // a **copy** of active is set into the list

Что, когда вы думаете об этом (по пространству), идентично:

_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(normal); // a **copy** of normal is set into the list

Обратите внимание, что копия не перейти в стек (структура = стек является распространенным мифом).Данные поступают в массив (внутри List<>), который находится в куче.Передача Arount структур по ссылке не будет иметь значения вообще к поведению Add (это просто позволяет избежать копирования структуры при передаче ее в этот метод, но копирование из памяти выполняется быстро).

1 голос
/ 23 марта 2010

Обратите внимание, что каждый раз, когда вы передаете структуру функции в качестве параметра или присваиваете одну переменную другой, или, в вашем случае, добавляете ее в список, создается копия всей структуры (в вашем случае 20 байтов).будет скопировано).

Также обратите внимание, что при некоторых обстоятельствах нет ссылок GC на структуры, ожидаемые (я думаю).


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

0 голосов
/ 23 марта 2010

Похоже, вы немного перепутали определение для типов значений и ссылочных типов. Структуры являются типами значений, поэтому переменные хранят фактические значения. Экземпляр структуры не является объектом, и он не будет собран GC. Переменная ссылочного типа хранит ссылку на экземпляр. Экземпляры хранятся в куче и в конечном итоге будут собраны GC.

Ваш список структур сам является ссылочным типом, поэтому он будет храниться в куче вместе со своими значениями. Каждый раз, когда вы добавляете запись в список, данные копируются из локального представления вашего метода в один из слотов в списке. Если вы сохраняете одно и то же значение несколько раз, оно будет скопировано несколько раз. Это просто список списка целых. Если у вас есть значение 42 десять раз, вы найдете десять копий значения 42 в памяти для списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...