我們現在要解釋IL是如何實現傳遞引用的。與C#不同,在IL中 可以很方便的使用指針。IL有3種類型的指針。
當函數abc被調用時,變量i會被作為一個引用參數 傳遞到函數中。在IL中,ldloca.s指令會被調用,它把變量的地址放到棧上。替代地,如果這個指令是 ldloc,那麼就會把變量的值放到棧上。
在函數調用中,我們添加符號&到類型名稱的結尾來 表示變量的地址。數據類型後面的&後綴表示變量的內存位置,而不是在變量中包括的值。
在 函數本身中,ldarg.1用於把參數1的地址放到棧上。然後,我們把想要初始化的數值放到棧上。在上面的 例子中,我們首先把變量i的地址放到棧上,隨後是我們想要初始化的值,即10。
stind指令把出 現在棧頂的值,也就是10,放到變量中,這個變量的地址存儲為棧上的第2項。在這個例子中,因為我們 傳遞變量i的地址到棧上,所以變量i分配到值10。
當在棧上給出一個地址時,使用stind指令。它 會使用特定的值填充該內存位置。
如果使用關鍵字ref取代out,那麼IL還是會顯示相同的輸出, 因為不管是哪種情形,變量的地址都會被放到棧上。因此,ref和out是C#實現中的“人為”概 念,而在IL中沒有任何等價的表示。
IL代碼無法知道原始的程序使用的是ref還是out。因此,在 反匯編這個程序時,我們將無法區別ref和out,因為這些信息在從C#代碼到IL代碼的轉換中會丟失。
a.cs
class zzz
{
public static void Main()
{
string s = "hi" + "bye";
System.Console.WriteLine(s);
}
}
a.il
.assembly mukhi {}
.class private auto ansi zzz extends [mscorlib]System.Object
{
.method public hidebysig static void vijay() il managed
{
.entrypoint
.locals (class System.String V_0)
ldstr "hibye"
stloc.0
ldloc.0
call void [mscorlib]System.Console::WriteLine(class System.String)
ret
}
}
Output
hibye