Nik*_*sev 3 .net stack cil arguments ilgenerator
在我的应用程序中,我需要动态创建一个包含多个属性的类型。我知道在这种情况下,必须使用 ILGenerator 为属性的 getter 和 setter 方法生成 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);
Run Code Online (Sandbox Code Playgroud)
该代码运行得很好,但有一件事我不明白。为什么需要调用‘Ldarg_0’指令?
我知道它引用了该方法的隐式第一个参数,即“this”引用,因此 setter 的实际值存储在第二个参数中。我认为仅调用 Ldarg_1 指令就足够了,这会将第二个参数推入堆栈(最后,在设置器中,我不需要检查“this”引用,因此我不需要对其进行任何操作),但这会导致当我尝试设置该属性的值时抛出 TargetInitationException 。
谢谢你!
如果您没有将“this”值压入堆栈,如何知道Stfld
要更改哪个对象的字段?您可能会尝试编写这样的设置器:
public int Bizarre\n{\n set { otherObject.Field = value; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n基本上,Stfld
记录表明堆栈上需要两个值:一个用于新值的“目标”,另一个用于值本身。诚然,ECMA 335 中的堆栈转换图更加清晰:
\xe2\x80\xa6, obj, value => \xe2\x80\xa6,\n
Run Code Online (Sandbox Code Playgroud)\n\n换句话说:“stfld 将从堆栈中弹出顶部的两个元素”。
\n 归档时间: |
|
查看次数: |
427 次 |
最近记录: |