OpCodes.Readonly Campo

Definizione

Specifica che la successiva operazione sull'indirizzo di matrice non comporta l'esecuzione di alcun controllo del tipo in fase di esecuzione e che viene restituito un puntatore gestito la cui modificabilità è limitata.

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 

Valore del campo

Commenti

La tabella seguente elenca il formato di assembly MSIL (Hexadecimal e Microsoft Intermediate Language) dell'istruzione, insieme a un breve riepilogo dei riferimenti:

Formato Formato assembly Descrizione
FE 1E readonly. Specificare che l'operazione di indirizzo della matrice successiva non esegue alcun controllo del tipo in fase di esecuzione e che restituisce un puntatore gestito con mutabilità limitata.

Questo prefisso può essere visualizzato immediatamente prima dell'istruzione ldelema e le chiamate al metodo speciale Address sulle matrici. L'effetto sull'operazione successiva è due volte:

  1. In fase di esecuzione non viene eseguita alcuna operazione di controllo dei tipi. Si noti che in genere è presente un controllo del tipo implicito per le ldelema istruzioni e stelem quando vengono usate nelle matrici di tipi di riferimento. Non esiste mai un controllo del tipo di runtime per le classi valore, quindi readonly in questo caso non è possibile eseguire alcuna operazione.

  2. Il verificatore considera il risultato dell'operazione address-of come puntatore gestito con mutabilità limitata.

Si dice che il puntatore abbia una mutabilità limitata perché il tipo di definizione controlla se il valore può essere modificato. Per le classi valore che non espongono campi pubblici o metodi che aggiornano il valore sul posto, il puntatore è di sola lettura (di conseguenza il nome del prefisso). In particolare, le classi che rappresentano tipi primitivi (ad esempio, System.Int32) non espongono i mutatori e pertanto sono di sola lettura.

Un puntatore gestito con restrizioni in questo modo può essere usato solo nei modi seguenti:

  • object Come parametro per le ldfldistruzioni , ldflda, stfld, calloconstrained callvirt .

  • pointer Come parametro per l'istruzione ldobj o per una delle ldind istruzioni.

  • source Come parametro dell'istruzionecpobj.

Tutte le altre operazioni non sono consentite, incluse le stobjoperazioni , initobjo mkrefany o una delle stind istruzioni.

Lo scopo del prefisso è evitare un controllo del tipo durante il readonly recupero di un elemento da una matrice nel codice generico. Ad esempio, l'espressione arr[i].m(), dove il tipo di elemento della matrice arr è un tipo generico vincolato ad avere un'interfaccia con il metodo m, potrebbe essere compilato nel codice MSIL seguente.

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

Senza il readonly prefisso , l'istruzione ldelema eseguirebbe un controllo del tipo nel caso in cui !0 fosse un tipo riferimento. Non solo questo tipo verifica inefficiente, ma è semanticamente errato. Il controllo del tipo è ldelema una corrispondenza esatta, che è troppo forte. Se la matrice contiene sottoclassi di tipo !0, il codice precedente non riuscirà a controllare il tipo.

L'indirizzo dell'elemento della matrice viene recuperato, anziché l'elemento stesso, per avere un handle per arr[i] che funzioni sia per i tipi valore che per i tipi riferimento, e quindi può essere passato all'istruzione constrained callvirt .

In generale, non sarebbe sicuro ignorare il controllo di runtime se la matrice contiene elementi di un tipo riferimento. Per essere sicuri, è necessario assicurarsi che non vengano apportate modifiche alla matrice tramite questo puntatore. Le regole di verifica assicurano questo. Il puntatore gestito con restrizioni può essere passato come oggetto di chiamate al metodo di istanza, pertanto non è strettamente di sola lettura per i tipi valore, ma non esiste alcun problema di sicurezza dei tipi di tipo per i tipi valore.

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

Si applica a