OpCodes.Readonly Поле

Определение

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

public: static initonly System::Reflection::Emit::OpCode Readonly;
public static readonly System.Reflection.Emit.OpCode Readonly;
 staticval mutable Readonly : System.Reflection.Emit.OpCode
Public Shared ReadOnly Readonly As OpCode 

Значение поля

Комментарии

В следующей таблице перечислены шестнадцатеричные и шестнадцатеричные и Microsoft формате сборки промежуточного языка (MSIL) инструкции, а также краткая сводка по ссылке:

Формат Формат сборки Description
FE 1E readonly. Укажите, что следующая операция адреса массива не выполняет проверку типа во время выполнения и возвращает управляемый указатель с ограниченной мутируемостью.

Этот префикс может отображаться только перед ldelema инструкцией и вызовами специального Address метода массивов. Его влияние на следующую операцию является двумя способами:

  1. Во время выполнения операция проверки типа не выполняется. Обратите внимание, что обычно выполняется проверка ldelema неявного типа и stelem инструкций при использовании в массивах ссылочных типов. В этом случае никогда не проверяется тип времени выполнения для классов значений, поэтому readonly в этом случае no-op.

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

Как говорят, указатель имеет ограниченную мутируемость, так как определяющий тип определяет, может ли значение быть мутировано. Для классов значений, которые не предоставляют открытых полей или методов, которые обновляют значение на месте, указатель доступен только для чтения (поэтому имя префикса). В частности, классы, представляющие примитивные типы (например, System.Int32), не предоставляют мутаторы и, следовательно, доступны только для чтения.

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

  • В object качестве параметра для ldfldпараметра , ldfldastfldили callconstrained callvirt инструкций.

  • В pointer качестве параметра инструкции ldobj или одной из инструкций ldind .

  • В source качестве параметра инструкции cpobj .

Все остальные операции запрещены, включая stobjinitobjоперации или mkrefany операции, или любые stind инструкции.

Цель readonly префикса заключается в том, чтобы избежать проверки типа при получении элемента из массива в универсальном коде. Например, выражение arr[i].m(), где тип элемента массива arr является универсальным типом, который был ограничен интерфейсом с методом m, может компилироваться в следующую MSIL.

ldloc arr
ldloc i
readonly.
ldelema !0    // Loads the pointer to the object.
…             // Load the arguments to the call.
constrained. !0
callvirt m

readonly Без префикса ldelema инструкция будет выполнять проверку типа в случае, когда !0 был ссылочным типом. Это не только проверка типа неэффективная, но и семантическая ошибка. Проверка ldelema типа — это точное совпадение, которое слишком сильно. Если массив содержит подклассы типа !0, приведенный выше код завершится ошибкой проверки типа.

Адрес элемента массива извлекается вместо самого элемента, чтобы иметь дескриптор, arr[i] который работает как для типов значений, так и ссылочных типов, и таким образом может быть передан инструкции constrained callvirt .

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

Следующая Emit перегрузка метода может использовать readonly код opcode:

Применяется к