.net 当用于自赋值时,编译器是否优化空合并运算符?
这两个代码块在功能上是相同的.net 当用于自赋值时,编译器是否优化空合并运算符?,.net,c#-4.0,.net,C# 4.0,这两个代码块在功能上是相同的 if (myObj == null) { myObj = new MyObj(); } 及 但是,在myObj不为null的情况下,使用null合并运算符的方法会执行不必要的赋值。但后来我想也许编译器会优化这些自赋值。有人知道编译器是否会注意到正在发生的事情,并将底部代码段转换为顶部代码段吗?刚刚在LinqPad中尝试过: void Main() { MyObj myObj = null; myObj = myObj ?? new MyOb
if (myObj == null)
{
myObj = new MyObj();
}
及
但是,在myObj不为null的情况下,使用null合并运算符的方法会执行不必要的赋值。但后来我想也许编译器会优化这些自赋值。有人知道编译器是否会注意到正在发生的事情,并将底部代码段转换为顶部代码段吗?刚刚在LinqPad中尝试过:
void Main()
{
MyObj myObj = null;
myObj = myObj ?? new MyObj();
}
这将产生以下IL:
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: brtrue.s IL_000C
IL_0006: pop
IL_0007: newobj UserQuery+MyObj..ctor
IL_000C: stloc.0
因此,无论
myObj
是否为空,赋值(stloc.0
在IL_000C)似乎都已完成。。。但也许JIT稍后会对此进行优化。为了比较,我尝试编译了这两个版本
object myObj = null;
myObj = myObj ?? new object();
及
Main
方法的内部。(我正在Mono2.6.7上使用MonoDevelop 2.4)
如果代码按预期进行了优化,我们应该会看到生成类似的IL。以下是第一个版本的Main
:
.method public static hidebysig
default void Main (string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
object V_0)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: brtrue IL_000f
IL_0009: pop
IL_000a: newobj instance void object::'.ctor'()
IL_000f: stloc.0
IL_0010: ret
}
第二个版本:
.method public static hidebysig
default void Main (string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
object V_0)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brtrue IL_000e
IL_0008: newobj instance void object::'.ctor'()
IL_000d: stloc.0
IL_000e: ret
}
因此,第一个版本(使用空合并操作符)生成了稍微多一些IL
但有两件事需要注意:
这是出于好奇,我意识到这是可以忽略的不同。请避免“过早优化”的评论:)为什么不检查使用?如果myObj是一个属性,那么可能的重复不一定相同。@Marcelo-有趣的是,如果它是一个属性,它可能会不同。你能再解释一下吗?既然
myObj
为空,那么作业当然就完成了。这就是空合并操作符的全部目的@肯,在这种情况下它是空的,但编译器没有考虑到这一点。。。该值可能来自其他地方,它将为myObj=myObj???生成相同的IL??新MyObj()对不起。恐怕我误解了这个问题的意图。
.method public static hidebysig
default void Main (string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
object V_0)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: brtrue IL_000f
IL_0009: pop
IL_000a: newobj instance void object::'.ctor'()
IL_000f: stloc.0
IL_0010: ret
}
.method public static hidebysig
default void Main (string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
object V_0)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brtrue IL_000e
IL_0008: newobj instance void object::'.ctor'()
IL_000d: stloc.0
IL_000e: ret
}