Подтвердить что ты не робот

Инициализация прямого массива с постоянным значением

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

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 выделяет новый массив и копирует значения в это впоследствии.

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();

Ответ 4

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

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

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