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 推入堆栈?

4

2 回答 2

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
}
于 2013-01-11T01:58:22.443 回答
2

如果方法不是静态的,则需要按声明和对象引用的顺序推送方法的参数。在您的测试用例中,您正在访问一个成员字段 ( s1),因此您需要this它的引用。这就是ldarg_0提供的。随后ldfld弹出this引用并将字段的值推送到评估堆栈上。

于 2013-01-11T01:56:18.983 回答