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

Array.Initialize - Почему этот метод существует?

Я наткнулся на метод сегодня. Я говорю о: Array.Initialize().

Согласно документации:

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

Как этот метод отвечает за создание типов значений поддержки компилятора? Насколько мне известно этот метод:

Инициализирует каждый элемент массива value-type, вызывая конструктор по умолчанию типа значения.

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

Даже когда мое намерение будет сбросить значения массива, я бы все равно не назвал его, я бы создал новый. array = new int[].

Итак, кажется, что этот метод существует только ради компилятора. Почему это? Может ли кто-нибудь дать мне более подробную информацию?

4b9b3361

Ответ 1

Стоит отметить, что правила .NET отличаются от правил С#.

Есть вещи, которые мы можем сделать в .NET, которые мы не можем сделать в С#, как правило, либо потому, что код не поддается проверке (например, ref типы возвращаемых данных), либо потому, что они могут ввести некоторую путаницу.

В С# struct не может быть определен конструктор без параметров, а вызов new SomeValueType() работает путем создания заполненной нулями части памяти (все поля, поэтому являются 0 для числовых типов, null для ссылочных типов и результат этого же правила снова для других типов значений).

В .NET вы можете иметь конструктор без параметров в типе значения.

Вероятно, это плохая идея. С одной стороны, правила только тогда, когда он вызывается, и только когда память значения заполнена нулем, а что происходит при назначении в разных случаях, не совсем просты (например, new SomeValueType() будет называть это, но new T() в общий метод, когда T SomeValueType не будет!). Жизнь проще, если результат new SomeValueType() всегда будет нулевым заполнением. Это, несомненно, повлияло на дизайн С#, не позволяя это, даже если .NET делает.

По этой причине Array.Initialize() никогда не будет иметь смысла в новых массивах любого типа, написанного на С#, потому что вызов конструктора и нулевое заполнение - это одно и то же.

Но тем не менее, возможно, что тип написан на другом языке .NET(по крайней мере, вы можете сделать это в CIL), у которого есть конструктор без параметров, который фактически имеет эффект. По этой причине его возможно, что компилятор для такого языка хотел бы, чтобы его эквивалент new SomeValueType[3] вызывал этот конструктор для всех типов в массиве. И поэтому разумно иметь метод в рамках, который позволяет сделать такую ​​заливку, чтобы компилятор для такого языка мог ее использовать.

Также, почему это публично?

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

Ответ 2

Для меня это похоже на то, что метод Initialize() запускается через массив и воссоздает типы значений внутри. Таким образом, с новым массивом вы получаете новый пустой массив, и вы получаете с Array.Clear(), но с Array.Initialize() вы получаете массив, полный свежих созданных типов значений (типы и длину, основанные на старом массиве).

И это должно быть все различие.

Ответ 3

На основе источника CLR метод обходит каждый индекс массива и инициализирует тип значения в этом индексе, вызывая конструктор по умолчанию, аналогично инструкции initobj IL (интересно, что происходит, когда конструктор генерирует исключение). Этот метод является общедоступным, потому что вызов частного метода непосредственно из IL сделает его немного непроверенным.

Сегодня компиляторы С# не инициализируют каждый элемент массива при его создании, просто "устанавливают" каждый индекс на значение по умолчанию для этого типа. В С# 6 внедряются конструкторы по умолчанию для типов значений (которые уже поддерживаются CLR), поэтому это необходимо для языков с различной семантикой создания массива.

Ответ 4

Вы можете увидеть ожидаемое использование в тестовом коде:

https://github.com/dotnet/coreclr/blob/3015ff7afb4936a1c5c5856daa4e3482e6b390a9/tests/src/CoreMangLib/cti/system/array/arrayinitialize.cs

В принципе, он устанавливает массив неинтерминированных значений в состояние по умолчанию (T).

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