Прямая инициализация массива с постоянным значением - PullRequest
46 голосов
/ 16 марта 2009

Каждый раз, когда вы выделяете новый массив в C # с помощью

new T[length]

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

В моем случае я хочу инициализировать массив Int32 значением -1:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

Таким образом, после того как память зарезервирована для массива, CLR зацикливается на вновь выделенной памяти и устанавливает все записи по умолчанию (int) = 0. После этого мой код устанавливает все записи в -1.

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

Ссылаясь на Инициализация массива C # - со значением, отличным от значения по умолчанию , использование Enumerable.Repeat(value, length).ToArray() не вариант, поскольку Enumerable.ToArray выделяет новый массив и копирует значения в него впоследствии.

Ответы [ 5 ]

33 голосов
/ 16 марта 2009

Это не избыточно.

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

Кстати, тот же аргумент справедлив для полей в объекте.

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

32 голосов
/ 29 сентября 2009

Аналогично ответу Дэна, но без необходимости использования коллекций:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
10 голосов
/ 16 марта 2009

Если вы купите в Массивы, считающиеся несколько вредными , тогда ваш вопрос будет спорным, как вы написали бы:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
3 голосов
/ 16 марта 2009

Я очень сомневаюсь, что JIT оптимизирует набор по умолчанию для этого сценария. Причина в том, что это будет заметная разница. Рассмотрим следующий слегка измененный сценарий.

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

Это вполне возможно для цикла, чтобы бросить. По крайней мере, JIT, вероятно, не сможет доказать это. Если это произойдет, и CLR не выполнит инициализацию памяти по умолчанию, результат будет заметен, если у вас все еще будет ссылка на obj.

0 голосов
/ 08 января 2019

Я предлагаю использовать Array.Fill как очень лаконичный способ заполнения массива начальным значением:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

При этом все значения в массиве isPrime инициализируются значением true.

...