次の方法で共有


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 

フィールド値

注釈

次の表に、命令の 16 進数および Microsoft 中間言語 (MSIL) アセンブリ形式と、簡単な参照の概要を示します。

形式 アセンブリ形式 説明
FE 1E Readonly。 後続の配列アドレス操作が実行時に型チェックを実行せず、変更可能性が制限されたマネージド ポインターを返すように指定します。

このプレフィックスは、命令の ldelema 直前にのみ出現し、配列の特殊な Address メソッドを呼び出します。 後続の操作に対するその影響は次の 2 つです。

  1. 実行時に、型チェック操作は実行されません。 参照型配列で使用される場合、通常、 および stelem 命令には暗黙的な型チェックldelemaがあることに注意してください。 値クラスには実行時の型チェックがないため、readonlyその場合は操作なしです。

  2. 検証ツールは、アドレスの操作の結果を、変更可能性が制限されたマネージド ポインターとして扱います。

ポインターは、値を変更できるかどうかを定義する型によって制御されるため、変更可能性が制限されると言われます。 値をインプレースで更新するパブリック フィールドまたはメソッドを公開しない値クラスの場合、ポインターは読み取り専用です (したがって、プレフィックスの名前)。 特に、プリミティブ型 (System.Int32 など) を表すクラスはミューテーターを公開しないため、読み取り専用です。

この方法で制限されたマネージド ポインターは、次の方法でのみ使用できます。

  • objectcallldfldastfldまたはconstrained callvirt 命令のldfldパラメーターとして指定します。

  • 命令またはpointer命令の ldind 1 つのパラメーターldobjとして。

  • 命令の source パラメーター cpobj として。

その他のすべての操作 (、、、またはmkrefany命令を含むstobjinitobj) はstind許可されていません。

プレフィックスのreadonly目的は、ジェネリック コード内の配列から要素をフェッチするときにチェック型を回避することです。 たとえば、配列arrの要素型が メソッドmとのインターフェイスを持つよう制約されているジェネリック型である 式 arr[i].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 使用できます。

適用対象