为什么有必要将每个参数加载到CIL方法中的堆栈上?
-
28-09-2019 - |
题
在我的应用程序中,我需要动态创建包含多个属性的类型。我知道,在这样的情况下,必须使用iLgenerator生成属性的ciL和setter方法。
通过反复试验,我终于到达了以下代码,该代码为我生成了一个六元的方法:
MethodBuilder setMethod = customTypeBuilder.DefineMethod(propertyName + "_set", MethodAttributes.Public | MethodAttributes.HideBySig, null, new Type[] {propertyType});
ILGenerator setIlGenerator = setMethod.GetILGenerator();
setIlGenerator.Emit(OpCodes.Ldarg_0);
setIlGenerator.Emit(OpCodes.Ldarg_1);
setIlGenerator.Emit(OpCodes.Stfld, backingField);
setIlGenerator.Emit(OpCodes.Ret);
该代码运行得足够好,但是我对此不了解一件事。 为什么需要调用“ LDARG_0”指令?
我知道它是指该方法的隐式第一个参数,即“此”参考,因此设置器的实际值存储在第二个参数中。我认为仅调用LDARG_1指令就足够了,这将第二个参数将堆栈推向堆栈(最后,在Setter中,我不需要检查“此”参考对此进行任何操作),但是这会导致当我尝试设置属性值时,抛出了targetInvocationException。
谢谢!
解决方案
如果您没有将“此”值推到堆栈上,该如何将如何 Stfld
知道要更改哪个对象字段?您可能正在尝试编写这样的二传手:
public int Bizarre
{
set { otherObject.Field = value; }
}
基本上, Stfld
是 记录 要在堆栈上需要两个值:一个用于新值的“目标”,一个用于值本身。诚然,ECMA 335中的堆栈过渡图更清晰:
…, obj, value => …,
换句话说:“ STFLD将在堆栈中弹出前两个元素”。
不隶属于 StackOverflow