}ページHome2012-10-25C#の"ref"引数のMSIL的取り扱い(.NETと参照渡し)TweetC#でrefを使ったメソッドのMSIL的作り方/呼び出し方(参照渡しの方法)についてメモしておく。サマリメソッドに渡す際は、アドレスを渡す。Cのポインタで言う&valのイメージ。ldloca命令を使う。メソッド内では、アドレスの解決を行う。Cのポインタで言う*aのイメージ。取得にはldind命令シリーズ(ldobj)、設定にはstind命令シリーズ(stobj)を使う。System.Int32&)Type.MakeByRefTypeでref型化、Type.GetElementTypeで非ref型化できる。ref型かどうかは、Type.IsByRefで判断できる。具体例として、参照を使うコードにありがちなSwapメソッドを作ってみる。y);}これをコンパイルしたものを逆アセンブルしたものが以下。Program::SampleFunc呼ばれるSwapメソッド適当に端折りながら、上から見ていく。(評価スタックのイメージを忘れてしまった場合は、この絵を思い出してほしい。)まずメソッドの定義。managedint32ではなく、int32&型が使われている。typeof(Int32).MakeByRefType();てな感じで得られる。x)を持ってくる持ってきたアドレスからint32の値を持ってくる0番目のローカル変数に格納するというイメージである。tmp;部分を見るとこう。y)を持ってくる0番目のローカル変数からint32の値を持ってくる持ってきたアドレスに持ってきた値を入れるというイメージである。yは上記の組み合わせ。stind.i4ここでは、int32なので、ldind.i4/stind.i4だが、型によって使うべき命令は違う。命令のショートカットです。[type]でもよい。int?を使うと、以下の感じで生成される。[mscorlib]System.Nullable`1Swap()を呼ぶメソッドこちらは実際に呼び出しているところだけ。int32&)10、20をそれぞれx、yに入れたあと、this、xのアドレス、yのアドレスの順に持ってきて、関数をコールしている。リフレクションでの扱いすでにあるメソッドのMethodInfoをGetMethod()で持ってきて、ParameterTypeを見ると、&のついたref型で入っている。この元の型を得たいときは、こんな感じになる。