Инициализация прямого массива с постоянным значением
Всякий раз, когда вы выделяете новый массив в С# с помощью
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, а если нет, существует ли способ напрямую инициализировать часть памяти с пользовательским значением?
Ссылаясь на инициализацию массива С# с значением, отличным от значения по умолчанию, использование Enumerable.Repeat(value, length).ToArray()
не является опцией, потому что Enumerable.ToArray
выделяет новый массив и копирует значения в это впоследствии.
Ответы
Ответ 1
Это не избыточно.
Предположим, что во время цикла инициализации возникает исключение. Если среда CLR не очистила память сначала, вы сможете "увидеть" оригинальную неинициализированную память, что является очень плохой идеей, особенно с точки зрения безопасности. Поэтому CLR гарантирует, что любая вновь выделенная память стирается до 0-битного шаблона.
Тот же аргумент сохраняется и для полей в объекте.
Я полагаю, что в обоих случаях CLR может проверить, что вы не собираетесь делать массив видимым в другом месте до завершения инициализации, но это сложная проверка, чтобы избежать довольно простой "протрите эту область памяти".
Ответ 2
Подобно Дэну, но без необходимости использования коллекций:
int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
Ответ 3
Если вы покупаете в массивы, которые считаются несколько вредными, тогда ваш вопрос будет спорным, как вы бы писали:
var myArray = new List<int>(Enumerable.Repeat(-1, 100));
Ответ 4
Я очень сомневаюсь, что JIT оптимизирует настройку по умолчанию для этого сценария. Причина в том, что это будет наблюдаемой разницей. Рассмотрим следующий слегка измененный сценарий.
obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }
Это вполне возможно для цикла. По крайней мере, для JIT, вероятно, невозможно доказать, что это не так. Если это было сделано, и среда CLR не инициализировала память по умолчанию, результат был бы наблюдаемым, если бы у вас все еще была ссылка на obj.