Выполняет ли System.Array бокс по типам значений или нет?

Недавно я сделал небольшое приблизительное измерение производительности List<> vs [] для массива небольших структур. System.Array, казалось, выиграл руки, поэтому я пошел с этим.

Мне просто казалось, что System.Array содержит типы объектов, поэтому, конечно, заполнение его структурами может привести к возникновению бокса?

Однако запись MSDN для System.Array гласит:

В .NET Framework версии 2.0 класс Array реализует System.Collections.Generic.IList<T> System.Collections.Generic.ICollection<T> и System.Collections.Generic.IEnumerable<T> общие интерфейсы. реализации выполняются в массивы во время выполнения, и поэтому не видны инструментам сборки документации. В результате общий интерфейсы не отображаются в синтаксисе объявления для массива класса, и нет никаких эталонных тем для членов интерфейса, которые доступны только путем заливки массива в общий тип интерфейса (явные реализации интерфейса).

Означает ли это, что бокс не происходит в конце концов? (И объяснил бы мои результаты работы)

Ответ 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> не вставляется. Независимо от использования списка или массива вы храните вещи в массиве.