WCF と IDispatchMessageInspector に関するいくつかの C# ドキュメントを読んでいます。インターフェイスは、操作できるように参照によって渡される「メッセージ」オブジェクトを定義します。
普通に渡すのではなく、ref で何かを渡すと、スタック上で実際に何が起こるでしょうか?
WCF と IDispatchMessageInspector に関するいくつかの C# ドキュメントを読んでいます。インターフェイスは、操作できるように参照によって渡される「メッセージ」オブジェクトを定義します。
普通に渡すのではなく、ref で何かを渡すと、スタック上で実際に何が起こるでしょうか?
参照によって渡されるのはオブジェクトではなく、変数です。
基本的に、呼び出し側から引数として使用される変数と、呼び出すメソッドのパラメーターにエイリアスを設定します。
public void Foo()
{
int x = 10;
Bar(ref x);
Console.WriteLine(x); // Prints 20
}
public void Bar(ref int y)
{
y = 20;
}
ここで、x
とy
は基本的に同じ変数であり、同じ格納場所を参照します。に加えられた変更はx
経由y
で表示され、その逆も同様です。(この場合、呼び出し元のローカル変数ですが、そうである必要はありません。インスタンス変数を参照で渡した場合Bar
、同じ変数を変更する別のメソッドを呼び出す可能性があり、それy
が表示されます。 「魔法のように」変化する...)
C# でのパラメーターの受け渡しの詳細については、件名に関する私の記事を参照してください。
参照とは、アイテムに渡された元の変数を変更できることを意味します。基本的に、変数の値ではなく、スタック上の変数のアドレスを渡します。
あなたが実際にスタックで実際に何が起こるかを尋ねたように、参照と値によるメソッドの IL ダンプがあります。
.method private hidebysig instance void ByRef(string& s) cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldstr "New value"
IL_0007: stind.ref
IL_0008: ret
} // end of method Class1::ByRef
対。
.method private hidebysig instance void ByValue(string s) cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "New value"
IL_0006: starg.s s
IL_0008: ret
} // end of method Class1::ByValue
ご覧のとおり、主な違いはパラメーターの型 (string&
ではなくstring
) であり、値を間接的に読み込んで保存するための追加の手順を実行します。
参考までに、簡単な C# ソースを以下に示します。
void ByRef(ref string s)
{
s = "New value";
}
void ByValue(string s)
{
s = "New value";
}
何かを値で渡すとき。値の型のコピーが作成され、関数が呼び出される前にスタックに置かれます。参照によって何かを渡すと、コピーを作成する代わりにそのアドレスがスタックにプッシュされ、関数内のオブジェクトを変更すると、コピーではなく元のオブジェクトが変更されます。
これが機能する方法は、引数が参照によって渡されたことを確認すると、コンパイラが変数への参照を間接メモリアクセスに変換することです。
たとえば、メモリ位置 100 に整数 123 があると仮定します。値で受け取る関数 (デフォルト) を呼び出すと、関数が呼び出される前に 123 のコピーが作成され、スタックにプッシュされます。これは、コピーが (たとえば) 160 アドレスにあることを意味します。ただし、参照によって何かを渡すと、アドレス 100 がスタックにプッシュされ、ロケーション 160 に常駐します。
これで、生成された命令は 160 を読み取ってオブジェクトの位置を取得し、100 でデータを変更します。* 演算子を使用した場合にポインターに対して行われるのと同じように間接化が行われます。
ref によって、渡されたオブジェクトに新しいインスタンスを作成できることを意味します。値によって、オブジェクトのプロパティを変更するだけではできません。