Compartir a través de


OpCodes.Readonly Campo

Definición

Especifica que la operación de dirección de matriz subsiguiente no realiza ninguna comprobación de tipo en tiempo de ejecución y devuelve un puntero administrado cuya mutabilidad está restringida.

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 

Valor de campo

Comentarios

En la tabla siguiente se muestra el formato de ensamblado hexadecimal y lenguaje intermedio de Microsoft (MSIL), junto con un breve resumen de referencia:

Formato Formato de ensamblado Descripción
FE 1E readonly. Especifique que la operación de dirección de matriz posterior no realiza ninguna comprobación de tipos en tiempo de ejecución y que devuelve un puntero administrado con mutabilidad restringida.

Este prefijo solo puede aparecer inmediatamente antes de la ldelema instrucción y las llamadas al método especial Address en matrices. Su efecto en la operación posterior es dos veces:

  1. En tiempo de ejecución, no se realiza ninguna operación de comprobación de tipos. Tenga en cuenta que normalmente hay una comprobación de tipo implícito para las ldelema instrucciones y stelem cuando se usan en matrices de tipos de referencia. Nunca hay una comprobación de tipo en tiempo de ejecución para las clases de valor, por lo que readonly es una operación sin operación en ese caso.

  2. El comprobador trata el resultado de la operación de dirección como un puntero administrado con mutabilidad restringida.

Se dice que el puntero tiene una mutabilidad restringida porque el tipo de definición controla si el valor se puede mutar. Para las clases de valor que no exponen campos o métodos públicos que actualizan el valor en contexto, el puntero es de solo lectura (por lo tanto, el nombre del prefijo). En concreto, las clases que representan tipos primitivos (por ejemplo, System.Int32) no exponen mutadores y, por tanto, son de solo lectura.

Un puntero administrado restringido de esta manera solo se puede usar de las siguientes maneras:

  • object Como parámetro para las ldfldinstrucciones , , callldfldastfld, oconstrained callvirt .

  • pointer Como parámetro de la ldobj instrucción o de una de las ldind instrucciones.

  • source Como parámetro de la cpobj instrucción .

Todas las demás operaciones no permitidas, incluidas las stobjinitobjoperaciones , o mkrefany o cualquiera de las stind instrucciones.

El propósito del readonly prefijo es evitar una comprobación de tipos al capturar un elemento de una matriz en código genérico. Por ejemplo, la expresión arr[i].m(), donde el tipo de elemento de la matriz arr es un tipo genérico que se ha restringido para tener una interfaz con el método m, podría compilarse en el siguiente MSIL.

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

Sin el readonly prefijo, la ldelema instrucción realizaría una comprobación de tipos en el caso de que !0 fuera un tipo de referencia. No solo es ineficaz esta comprobación de tipos, pero es semánticamente incorrecta. La comprobación de tipo de ldelema es una coincidencia exacta, que es demasiado fuerte. Si la matriz contiene subclases de tipo !0, el código anterior producirá un error en la comprobación de tipos.

La dirección del elemento de matriz se captura, en lugar del propio elemento, con el fin de tener un identificador para que funcione tanto arr[i] para los tipos de valor como para los tipos de referencia, y por lo tanto se puede pasar a la constrained callvirt instrucción .

En general, no sería seguro omitir la comprobación en tiempo de ejecución si la matriz tenía elementos de un tipo de referencia. Para ser seguro, es necesario asegurarse de que no se realicen modificaciones en la matriz a través de este puntero. Las reglas del comprobador garantizan esto. El puntero administrado restringido se puede pasar como objeto de llamadas de método de instancia, por lo que no es estrictamente de solo lectura para los tipos de valor, pero no hay ningún problema de seguridad de tipos para los tipos de valor.

La sobrecarga del método siguiente Emit puede usar el readonly código de operación:

Se aplica a