#c# #list #memory-management
#c# #Список #управление памятью
Вопрос:
У меня есть тонны объектов одного и того же класса obj
, которые в настоящее время определены как obj[]
.
В большинстве случаев это obj
просто default(obj)
, не было бы лучше реализовать IEnumerable<obj>
вместо этих obj[]
списков?
Это должно освободить память для меня, верно? В настоящее время количество этих объектов (под управлением профилировщика памяти) составляет 200 тыс. элементов (постоянно растет).
Помогло бы мне изменение списков на IEnumerables?
Ответ №1:
Фактическая реализация List<T>
основана на массивах, поэтому разница в использовании памяти между ними будет незначительной.
Что касается IEnumerable<T>
: нет, это не сэкономит вам никакой памяти. элементы null
or default
вполне приемлемы в IEnumerable<T>
, и фреймворк ничего не делает для фильтрации дубликатов. Это невозможно, поскольку объем памяти, связанный со IEnumerable<T>
структурой, полностью зависит от класса, который ее реализует, и если вы просто помещаете массив в перечислимую переменную или поле, то вы ничего существенного не меняете. Перечислимые также неизменяемы, поэтому предлагаемый переключатель, вероятно, был бы кардинальным изменением по сравнению с вашей реализацией массива.
Если вас не волнует порядок, вы можете использовать HashSet<T>
. На самом деле это выполняет фильтрацию дубликатов, поэтому, если многие или большинство ваших элементов являются таковыми default(T)
, то вам потребуется память только для одного из них. Очевидно, что это устранит все дубликаты, а не только те, что по умолчанию, поэтому этот выбор был бы полезен только в том случае, если нет другого дублирования.
Если вам требуется изменяемая семантика — как я подозреваю, вы делаете, если используете массивы, — тогда вы могли бы (и должны) переключиться на изменяемый интерфейс, такой как IList<T>
, и написать свою собственную реализацию — вероятно, основанную на List<T>
— которая игнорирует default(T)
при попытке ее добавить. Таким образом, вы могли бы сохранить порядок не- default
элементов, никогда не выделяя никакой памяти для хранения default
них.
Если вам действительно нужно сохранить все исходные элементы, то никакая простая структура данных вам не поможет. Могу ли я предложить базу данных? Я знаю, что в наши дни памяти в избытке, но когда вы храните сотни тысяч элементов, вы должны, по крайней мере, учитывать структуру данных или систему, рассчитанную на этот масштаб.
Ответ №2:
IEnumerable
это просто интерфейс; он не предписывает какой-либо способ хранения данных. List
Просто содержит массив, который увеличивается по мере добавления в него новых элементов, но вы можете вызвать TrimExcess()
метод для уменьшения массива.
Ответ №3:
Как сказал Марк, IEnumerable — это просто интерфейс. Object[] и List (и большинство других общих коллекций в .NET framework) фактически реализует интерфейс IEnumerable.
Более уместным вопросом было бы, что лучше: Object [] или List или LinkedList и т.д.
Массив объектов (т.Е. Object[]) будет иметь наименьший объем памяти, поскольку размер списка может в два раза превышать объем памяти массива (в зависимости от того, сколько элементов в списке). Когда вы добавляете элемент в список, а внутренний массив заполнен, это удваивает размер массива в попытке ускорить добавление новых элементов в среднем с алгоритмической точки зрения.