Ответ 1
Без использования массива не используется поле, если вы используете нотацию индексатора. например.
new int[2];
x=[1]=3;
Скомпилируется для следующего IL (обратите внимание, что номера строк не имеют значения, поскольку они исходят из некоторого другого фрагмента кода)
IL_0011: ldc.i4.2
IL_0012: newarr System.Int32
IL_0017: stfld Int32[] x
IL_001c: ldarg.0
IL_001d: ldfld Int32[] x
IL_0022: ldc.i4.1
IL_0023: ldc.i4.3
IL_0024: stelem.i4
Для языков, которые не могут использовать индексатор (и я действительно не знаю, существуют они или нет), во время компиляции для массивов создаются 2 других метода.
Он создает эти общедоступные методы::
public int Get(int index)
public void Set(int index,int value)
Эти методы также не устанавливаются в поле и обычно недоступны через С#. (Не спрашивайте меня, почему они являются общедоступными методами). Вы можете выполнить их с помощью IL или путем создания для них делегатов. Они медленнее, поскольку вы вынуждены делать callvirt для вызова этих методов.
Семейство stelem. * и ldelem. * используется для управления хранением строго типизированного типа массива. При использовании дженериков обычно используются следующие префиксы constrained
или readonly
при использовании T[]
. stelem.*
тип обычно не проверяет тип. Например. использование stelem.i4
выполняется быстрее, чем использование stelem.any Int32
, если вы не префикс его readonly
, потому что в противном случае он заставляет проверку типа.
Теперь typecheck ПОЛНОСТЬЮ бесполезен для массивов valuetype, они не ковариантны!
Поскольку среда выполнения генерирует одномерный массив, начинающийся с нуля (или называемый SZ_array или векторный тип), они изначально известны.
Для них существует семейство оппортовых кодов: newarr
, stelem.*
, ldelem.*
, ldlen
и т.д.
Тип List<T>
использует T[]
для своего резервного хранилища в реализации Microsoft BCL. List<T>
не вставляется. Независимо от использования списка или массива вы храните вещи в массиве.