Condividi tramite


OpCodes.Constrained Campo

Definizione

Vincola il tipo su cui viene effettuata una chiamata al metodo virtuale.

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 

Valore del campo

Commenti

La tabella seguente elenca il formato di assembly MSIL (Esadecimale e MSIL) dell'istruzione, insieme a un breve riepilogo di riferimento:

Formato Formato assembly Descrizione
FE 16 <T> obbligato. thisType Chiamare un metodo virtuale su un tipo vincolato per essere di tipo T.

Il prefisso constrained è consentito solo in un'istruzione callvirt.

Lo stato dello stack MSIL a questo punto deve essere il seguente:

  1. Un puntatore gestito, ptr, viene inserito nello stack. Il tipo di ptr deve essere un puntatore gestito (&) per thisType. Si noti che questo comportamento è diverso dal caso di un'istruzione callvirt senza prefisso, che prevede un riferimento di thisType.

  2. Gli argomenti del metodo arg1 tramite argN vengono inseriti nello stack, come con un'istruzione callvirt senza prefisso.

Il prefisso constrained è progettato per consentire l'applicazione di istruzioni callvirt in modo uniforme indipendente dal fatto che thisType sia un tipo valore o un tipo riferimento.

Quando un'istruzione callvirtmethod è stata preceduta da constrainedthisType, l'istruzione viene eseguita come segue:

  • Se thisType è un tipo riferimento (anziché un tipo valore), ptr viene dereferenziato e passato come puntatore "this" al callvirt di method.

  • Se thisType è un tipo valore e thisType implementa method, ptr viene passato come puntatore "this" a un'istruzione callmethod, per l'implementazione di method da parte di thisType.

  • Se thisType è un tipo valore e thisType non implementa method, ptr viene dereferenziato, boxed e passato come puntatore "this" all'istruzione callvirtmethod.

Questo ultimo caso può verificarsi solo quando method è stato definito in Object, ValueTypeo Enum e non sottoposto a override da thisType. In questo caso, il boxing fa sì che venga eseguita una copia dell'oggetto originale. Tuttavia, poiché nessuno dei metodi di Object, ValueTypee Enum modificare lo stato dell'oggetto, questo fatto non può essere rilevato.

Il prefisso constrained supporta i generatori IL che creano codice generico. In genere l'istruzione callvirt non è valida per i tipi valore. È invece necessario che i compilatori IL eseguano in modo efficace la trasformazione "this" descritta in precedenza in fase di compilazione, a seconda del tipo di ptr e del metodo chiamato. Tuttavia, quando ptr è un tipo generico sconosciuto in fase di compilazione, non è possibile eseguire questa trasformazione in fase di compilazione.

Il codice operativo constrained consente ai compilatori IL di effettuare una chiamata a una funzione virtuale in modo uniforme indipendentemente dal fatto che ptr sia un tipo valore o un tipo riferimento. Anche se è destinato al caso in cui thisType è una variabile di tipo generico, il prefisso constrained funziona anche per i tipi non generici e può ridurre la complessità della generazione di chiamate virtuali in linguaggi che nascondono la distinzione tra tipi valore e tipi di riferimento.

L'uso del prefisso constrained evita anche potenziali problemi di controllo delle versioni con i tipi valore. Se il prefisso constrained non viene utilizzato, è necessario generare un'istruzione IL diversa a seconda che un tipo di valore esesti o meno un metodo di System.Object. Ad esempio, se un tipo valore V esegue l'override del metodo Object.ToString(), viene generata un'istruzione callV.ToString(); in caso contrario, vengono generate un'istruzione box e un'istruzione callvirtObject.ToString(). Un problema di controllo delle versioni può verificarsi nel caso precedente se l'override viene rimosso in un secondo momento e in quest'ultimo caso se viene aggiunto un override in un secondo momento.

Il prefisso constrained può essere usato anche per la chiamata di metodi di interfaccia sui tipi valore, perché il metodo di tipo valore che implementa il metodo di interfaccia può essere modificato usando un MethodImpl. Se il prefisso constrained non viene usato, il compilatore deve scegliere a quale dei metodi del tipo valore associare in fase di compilazione. L'uso del prefisso constrained consente al MSIL di eseguire il binding al metodo che implementa il metodo di interfaccia in fase di esecuzione, anziché in fase di compilazione.

L'overload del metodo Emit seguente può usare il codice operativo constrained:

Si applica a