Как и когда отказаться от использования массивов в C#?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

25
задан Keng 18 July 2013 в 13:08
поделиться

14 ответов

Посмотрите на дженерик List<T> как замена для массивов. Они поддерживают большинство массивов того же самого, делают, включая выделение размера исходной системы хранения, если Вы хотите.

22
ответ дан Joel Coehoorn 28 November 2019 в 20:34
поделиться

Лучшая вещь, которую можно сделать, состоит в том, чтобы выделить столько памяти, сколько Вам нужно заранее, если это возможно. Это предотвратит .NET от необходимости выполнить дополнительные вызовы для получения памяти на "куче". При сбое этого тогда, которое имеет смысл выделять в блоках пять или независимо от того, что число имеет смысл для приложения.

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

1
ответ дан Peter Mortensen 28 November 2019 в 20:34
поделиться

Если Вы собираетесь быть выполнением большого добавления, , и Вы не будете делать произвольного доступа (такой как myArray[i]). Вы могли рассмотреть использование связанного списка (LinkedList<T>), потому что это никогда не должно будет "расти" как List<T> реализация. Следует иметь в виду, тем не менее, что можно только действительно получить доступ к объектам в LinkedList<T> реализация с помощью эти IEnumerable<T> интерфейс.

1
ответ дан Michael Meadows 28 November 2019 в 20:34
поделиться

Если я думаю, что собираюсь быть добавляющими объектами к набору много за его время жизни, чем я буду использовать Список. Если я буду знать наверняка, чем будет размер набора, когда его заявленное, то я буду использовать массив.

Другое время я обычно использую массив по Списку, когда я должен возвратить набор как свойство объекта - я не хочу вызывающие стороны, добавляющие объекты, что набор с помощью Списка Добавляет методы, но вместо этого хочет, чтобы они добавили объекты к набору через интерфейс моего объекта. В этом случае я возьму внутренний Список и назову ToArray и возвращу массив.

1
ответ дан John Christensen 28 November 2019 в 20:34
поделиться

Это сообщение форума могло бы или не могло бы быть несколько полезным Вам относительно эффективности различных типов массива: массивы C# - многомерный по сравнению с лексикографическим

1
ответ дан Grank 28 November 2019 в 20:34
поделиться

Вы корректны, массив является большим для взлетов взгляда. Однако модификации к размеру массива являются дорогостоящими.

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

Или Вы могли просто использовать связанный список. Тогда однако посмотрите, взлеты являются медленными...

1
ответ дан Sam 28 November 2019 в 20:34
поделиться

Стандартный массив должен быть определен с длиной, которая резервирует всю память, в которой он нуждается в непрерывном блоке. Добавление объекта к массиву вставило бы его блока уже зарезервированной памяти.

1
ответ дан user13288 28 November 2019 в 20:34
поделиться

Массивы являются большими для немногих записей и многих чтений, особенно те из повторяющейся природы - для чего-либо еще, используют одну из многих других структур данных.

1
ответ дан Greg Hurlman 28 November 2019 в 20:34
поделиться

ArrayList и Список выращивают массив на больше чем один при необходимости (я думаю, что это путем удвоения размера, но я не проверил источник). Они - обычно лучший выбор, когда Вы создаете динамично размерный массив.

то, Когда Ваши сравнительные тесты указывают, что массив изменяет размеры, серьезно замедляется, Ваше приложение (помните - преждевременная оптимизация является корнем всего зла), можно оценить запись пользовательского класса массива с настроенным поведением изменения размеров.

2
ответ дан Tom Ritter 28 November 2019 в 20:34
поделиться

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

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

2
ответ дан Abe Heidebrecht 28 November 2019 в 20:34
поделиться

Если Вы собираетесь быть добавляющими/удаляющими элементами много, просто используйте Список. Если это многомерно, можно всегда использовать List< List< интервал>> или что-то.

, С другой стороны, списки менее эффективны, чем массивы, если то, что Вы главным образом делаете, пересекающий список, потому что массивы - все в одном месте в Вашем кэше ЦП, где объекты в списке рассеиваются повсеместно.

, Если Вы хотите использовать массив для эффективного чтения, но Вы часто собираетесь быть "добавляющими" элементами, у Вас есть две основных опции:

1) Генерируют его как Список (или Список Списков) и затем используют ToArray () для превращения его в эффективную структуру массива.

2) Выделяют массив, чтобы быть больше, чем Вы нуждаетесь, затем помещаете объекты в предварительно выделенные ячейки. Если Вы заканчиваете тем, что нуждались еще в большем количестве элементов, чем Вы предварительно выделили, можно просто перераспределить массив, когда он заполняется, удваивая размер каждый раз. Это дает O (зарегистрируйте n), изменение размеров производительности вместо O (n) как он было бы с массивом reallocate-once-per-add. Обратите внимание, что это в значительной степени, как StringBuilder работает, давая Вам более быстрый способ постоянно добавить к строке.

3
ответ дан apenwarr 28 November 2019 в 20:34
поделиться

В целом я предпочитаю избегать использования массива. Просто используйте List< T>. Это использует динамично измеренный массив внутренне и достаточно быстро для большей части использования. При использовании массивов multi-dimentional используйте List< List< List< T>>>, если Вы имеете к. Дело не в этом намного хуже с точки зрения памяти, и намного более просто добавить объекты к.

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

4
ответ дан Jonathan Rupp 28 November 2019 в 20:34
поделиться

Это действительно зависит от того, под чем Вы подразумеваете, "добавляют".

, Если Вы имеете в виду:

T[] array;
int i;
T value;
...
if (i >= 0 && i <= array.Length)
    array[i] = value;

Затем нет, это не создает новый массив и является на самом деле самым быстрым способом изменить любой вид IList в.NET.

, однако, при использовании чего-то как ArrayList, Список, Набор, и т.д. затем называя "Добавить" метод может создавать новый массив - но они умны об этом, они только изменяют размеры 1 элементом, они растут геометрически, поэтому если Вы добавляете, что много значений только время от времени будет, это должно выделить новый массив. Даже тогда можно использовать свойство "Capacity", чтобы вынудить его вырасти перед рукой, если Вы знаете, сколько элементов Вы добавляете (list.Capacity += numberOfAddedElements)

12
ответ дан Alex Lyman 28 November 2019 в 20:34
поделиться

Обычно, если у Вас должно быть ЛУЧШЕЕ индексируемое выполнение поиска, лучше создавать Список сначала и затем превращать его в массив, таким образом платя маленький штраф сначала, но избежав немного позже. Если проблема - то, что Вы будете постоянно добавлять новые данные и удалять старые данные тогда, можно хотеть использовать ArrayList или Список для удобства, но иметь в виду, что они - просто Массивы особого случая. Когда они "растут", они выделяют абсолютно новый массив и копируют все в него, которое является чрезвычайно медленным.

ArrayList является просто Массив, который растет при необходимости. Добавьте амортизируется O (1), просто стараться удостовериться, что изменения размеры не произойдет в плохое время. Вставка является O (n), все объекты направо должны быть отодвинуты. Удалите O (n), все объекты направо должны быть отодвинуты.

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

лучшая вещь сделать состоит в том, чтобы выбрать структуру данных, которая соответствует Вашей проблеме. Это зависит тот МНОГО вещей и таким образом, можно хотеть просмотреть Система. Наборы. Универсальный Пространство имен.

В данном случае я сказал бы, что, если бы можно придумать хорошее значение ключа , Словарь был бы лучшим выбором. Это имеет, вставляют и удаляют, который приближается к O (1). Однако даже со Словарем необходимо быть осторожными, чтобы не позволить ему изменить размеры, это - внутренний массив (O (n) операция). Лучше давать им много комнаты путем определения larger-then-you-expect-to-use начальной способности в конструкторе.

- Рик

2
ответ дан Rick Minerich 28 November 2019 в 20:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: