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 

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

Комментарии

В следующей таблице перечислены шестнадцатеричный формат инструкции и сборки msil и краткие справочные сведения:

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

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

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

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

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

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

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

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

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

Все остальные операции запрещены, включая stobjоперации , initobjили 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 метода может использовать код операции:

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