2015-11-25 4 views
23

Я наткнулся на метод сегодня. Речь идет о: Array.Initialize().Array.Initialize - Почему этот метод существует?

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

This method is designed to help compilers support value-type arrays; most users do not need this method.

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

Initializes every element of the value-type Array by calling the default constructor of the value type.

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

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

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

+0

И если вы хотите сбросить значения без создания нового массива, вы, вероятно, также должны использовать 'Array.Clear()'. –

+8

Закрыть? Мне кажется, это правильный вопрос. Может быть, вы просто проголосовали за закрытие по названию? Я знаю. Почему этот метод существует? Какая-то сложность, но если вы прочитаете все вопросы, я уверен, вы согласитесь со мной. –

+1

@ SonerGönül «Почему была разработана такая схема?» - это вопрос о людях, которые его спроектировали. Кто-нибудь еще собирается угадать. Вопрос не подходит для SO; если вы хотите знать, почему Microsoft разработала .NET таким образом, спросите их *. – Servy

ответ

11

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

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

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

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

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

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

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

Also, why is it public?

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

+1

«Теперь вы можете сделать это с помощью C# 6»: нет, вы не можете. Эта функция была рассмотрена, и IIRC был даже реализован в одной из предварительных версий, но в конечном итоге был снят. В окончательной версии вы получите эту ошибку: 'CS0568 Structs не может содержать явные конструкторы без параметров –

+1

@ThomasLevesque ah, спасибо, вы можете сказать, что я еще не играл с последней версией! Также хорошо! Вексели безпараметрических конструкторов на типах значений, вероятно, не стоили бы этого. –

1

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

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

+0

Предположим, что у меня есть 'int [] a = new int [3] {7, 9, 13,};' в C#. Ваш ответ _could_ должен быть прочитан как означающий, что если я сделаю 'a.Initialize();' на этом, то после этого у меня будет массив нулей ('default (int)'). Однако это неправильно. Если вы хотите эту функцию, используйте вместо нее 'Array.Clear (a, 0, a.Length);'. –

0

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

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

0

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

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

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

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

Смежные вопросы