我有一个类,它有一个类型为泛型Stack的私有变量
在课堂上我宣布了一个Foo方法
在检查了IL之后,我注意到方法Push的目标实际上是方法调用set_Property2而不是类的字段。
编译器如何实际建立两者之间的连接?
public class A
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
public class ShortDemo
{
private Stack<A> _stack = new Stack<A>();
private void Foo()
{
_stack.Push(new A()
{
Property1 = 1,
Property2 = 2
});
}
}
和IL:
.method private hidebysig instance void Foo() cil managed
{
.maxstack 3
.locals init (
[0] class ConsoleApplication1.A g__initLocal0)
L_0000: nop
L_0001: ldarg.0
L_0002: ldfld class [System]System.Collections.Generic.Stack1 ConsoleApplication1.ShortDemo::_stack
L_0007: newobj instance void ConsoleApplication1.A::.ctor()
L_000c: stloc.0
L_000d: ldloc.0
L_000e: ldc.i4.1
L_000f: callvirt instance void ConsoleApplication1.A::set_Property1(int32)
L_0014: nop
L_0015: ldloc.0
L_0016: ldc.i4.2
L_0017: callvirt instance void ConsoleApplication1.A::set_Property2(int32)
L_001c: nop
L_001d: ldloc.0
L_001e: callvirt instance void [System]System.Collections.Generic.Stack1::Push(!0)
L_0023: nop
L_0024: ret
}
答案 0 :(得分:2)
我没有看到问题。以下是选项:
A a = new A() { ... };
_stack.Push(args)
转换为:
现在你的“嵌入式”对象初始化版本:
_stack.Push(new A() { ... });
转换为:
在这两种情况下,堆栈都以字段和参数结束。只是在“嵌入式”对象初始化程序版本中,加载字段和调用方法之间会有更多的东西。
答案 1 :(得分:0)
根据反射器
L_0001:“this”引用位于顶部
L_0002:从堆栈中弹出值后,字段引用位于顶部
L_0007:新的ConsoleApplication1.A对象位于顶部
L_000c:从堆栈中弹出值后,赋值表达式位于顶部
(所以现在我们在顶部和字段引用分配了两个表达式)
L_000d:顶部的可变参考。
L_000e:顶部的文字int值
L_000f:弹出文字值后,在顶部调用set_Property1方法,用作参数,变量引用用作目标。
(现在我们有3个表达式方法调用set_Property1,赋值表达式然后字段
参考)。
L_0017:与在堆栈的方法调用添加中结束的L_000f相同
(set_Property2,set_Property1,assign,field reference)。
L_001d:可变参考
(变量引用,set_Property2,set_Property1 ......)
L_001e:push方法需要一个目标和一个参数。如果我假设此行与行L_000f的作用相同,则堆栈顶部的目标为set_Property2。
我不明白为什么你写这个堆栈最终会得到字段和参数。