有人能向我解释一下在通过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)
}
}
我有一份上面测试的副本供参考,我注意到在"调用"之前发出了以下操作码。
- ldarg_1
- ldarg_0
- ldfld
问题是ldarg_0在那里做什么?调用只需要2个参数,为什么CLR需要将ldarg_0推送到堆栈?
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
}
如果方法不是静态的,则需要按声明和对象引用的顺序推送方法的参数。在您的测试用例中,您正在访问一个成员字段(s1
(,因此您需要它的this
引用。这就是ldarg_0
所提供的。随后的ldfld
弹出this
引用,并将字段的值推送到评估堆栈上。