如果S s;
使用{struct S{}
声明构造函数,则通过调用其构造函数(例如a = new S(11)
)初始化值类型局部变量(例如S
给定int
) {1}}参数。然后new S(11)
编译为:
ldloca.s V_0
ldc.i4.s 11
call instance void S::.ctor(int32)
但是当s
是一个字段(例如class C { S s;
)时,它不会以相同的方式初始化。关于类C
的以下实例方法:void setS(int n) { s = new S(n); }
它将编译为:
ldarg.0
ldarg.1
newobj instance void S::.ctor(int32)
stfld valuetype S C::s
我原以为它会编译成以下代码,这更接近局部变量的情况:
ldarg.0
ldflda valuetype S C::s
ldarg.1
call instance void S::.ctor(int32)
此外,如果我清楚地理解,newobj instance void S::.ctor(int32)
有更高的开销并且负担GC。我是对的吗?
为什么,C#编译器使用值类型字段的方法与用于局部变量的方法不同?
答案 0 :(得分:4)
基本上,为了将构造函数调用与赋值分开,需要此行为。
预期的可观察行为是,如果构造函数抛出异常,则分配不会发生。在"优化"中不会出现这种情况。构造函数直接写入字段/堆栈插槽的版本。
在分配给本地变量时,您可以看到相同的IL:
不完全相同的问题,但有更多详细信息in this SO post和Eric Lippert's blog。