2013-01-11 29 views
5

有人可以向我解釋什麼需要在通過reflection.emit進行函數調用之前加載到堆棧中?反射發射堆棧和方法調用

我有一個非常簡單的方法

public static void Execute(string 1, string 2) 

我要動態地生成在下面的類的方法(忘了休息,我讓他們整理)

public class Test{ 
    public string s1; 

    public void Run(string s2) 
    { 
     MyOtherClass.Execute(s2,s1) 
    } 
} 

我有一個副本以上的測試,以供參考,並且我注意到在「調用」之前發射了以下操作碼。

  1. ldarg_1
  2. ldarg_0
  3. ldfld

的問題是什麼ldarg_0在那裏做什麼?爲了調用,我只需要2個參數,爲什麼CLR要求ldarg_0被推入堆棧?

+0

你能提供周圍的IL嗎? –

回答

9

arg.0包含this並且ldfld string Test:s1要求將this.s1推到堆棧上。

.method public hidebysig instance void Run(string s2) cil managed 
{ 
    .maxstack 8          // maximum stack size 8 
    ldarg.1           // push argument s2 
    ldarg.0           // push this 
    ldfld string Test::s1       // pop this, push this.s1 
    call void MyOtherClass::Execute(string, string) // call 
    ret            // return 
} 
+0

謝謝!我知道我現在錯過了什麼。 – Alwyn

2

如果方法不是靜態的,則需要按聲明和對象引用的順序推送方法的參數。在您的測試案例中,您正在訪問成員字段(s1),因此您需要參考this。這就是ldarg_0提供的。隨後的ldfld彈出this參考並將該字段的值推送到評估堆棧。