Comparteix a través de


OpCodes.Constrained Campo

Definición

Restringe el tipo en el que se realiza una llamada de método virtual.

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

Valor de campo

Comentarios

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

Formato Formato de ensamblado Descripción
FE 16 <T> encogido. thisType Llame a un método virtual en un tipo restringido para que sea de tipo T.

El prefijo constrained solo se permite en una instrucción callvirt.

El estado de la pila MSIL en este punto debe ser el siguiente:

  1. Un puntero administrado, ptr, se inserta en la pila. El tipo de ptr debe ser un puntero administrado (&) para thisType. Tenga en cuenta que esto es diferente del caso de una instrucción callvirt sin prefijo, que espera una referencia de thisType.

  2. Los argumentos de método arg1 a través de argN se insertan en la pila, al igual que con una instrucción callvirt sin prefijo.

El prefijo constrained está diseñado para permitir que callvirt instrucciones se realicen de forma uniforme independientemente de si thisType es un tipo de valor o un tipo de referencia.

Cuando constrainedthisTypeha prefijo una instrucción callvirtmethod , la instrucción se ejecuta de la siguiente manera:

  • Si thisType es un tipo de referencia (en lugar de un tipo de valor), ptr se desreferencia y se pasa como puntero "this" al callvirt de method.

  • Si thisType es un tipo de valor y thisType implementa method, ptr se pasa sin modificar como puntero "this" a una instrucción callmethod, para la implementación de method mediante thisType.

  • Si thisType es un tipo de valor y thisType no implementa method, ptr se desreferencia, boxed y se pasa como puntero "this" a la instrucción callvirtmethod.

Este último caso solo puede producirse cuando method se definió en Object, ValueTypeo Enum y no se invalidó thisType. En este caso, la conversión boxing hace que se realice una copia del objeto original. Sin embargo, dado que ninguno de los métodos de Object, ValueTypey Enum modificar el estado del objeto, no se puede detectar este hecho.

El prefijo constrained admite generadores de IL que crean código genérico. Normalmente, la instrucción callvirt no es válida en los tipos de valor. En su lugar, es necesario que los compiladores de IL realicen eficazmente la transformación "this" descrita anteriormente en tiempo de compilación, según el tipo de ptr y el método al que se llama. Sin embargo, cuando ptr es un tipo genérico desconocido en tiempo de compilación, no es posible realizar esta transformación en tiempo de compilación.

El constrained código de operación permite a los compiladores de IL realizar una llamada a una función virtual de forma uniforme independientemente de si ptr es un tipo de valor o un tipo de referencia. Aunque está pensado para el caso en el que thisType es una variable de tipo genérico, el prefijo constrained también funciona para tipos no genéricos y puede reducir la complejidad de generar llamadas virtuales en lenguajes que ocultan la distinción entre los tipos de valor y los tipos de referencia.

El uso del prefijo constrained también evita posibles problemas de control de versiones con tipos de valor. Si no se usa el prefijo constrained, se debe emitir una IL diferente en función de si un tipo de valor invalida o no un método de System.Object. Por ejemplo, si un tipo de valor V invalida el método Object.ToString(), se emite una instrucción callV.ToString(); si no es así, se emiten una instrucción box y una instrucción callvirtObject.ToString(). Puede surgir un problema de control de versiones en el caso anterior si la invalidación se quita más adelante y, en este último caso, si se agrega una invalidación más adelante.

El prefijo constrained también se puede usar para invocar métodos de interfaz en tipos de valor, ya que el método de tipo de valor que implementa el método de interfaz se puede cambiar mediante un MethodImpl. Si no se usa el prefijo constrained, el compilador se ve obligado a elegir a cuál de los métodos del tipo de valor se enlazan en tiempo de compilación. El uso del prefijo constrained permite que el MSIL se enlace al método que implementa el método de interfaz en tiempo de ejecución, en lugar de en tiempo de compilación.

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

Se aplica a