无效合并算子的使用不当?

myFoo = myFoo ?? new Foo(); 

代替

 if (myFoo == null) myFoo = new Foo(); 

我是否认为第一行代码始终执行赋值是正确的? 另外,这是空合并运算符的错误用法吗?

我比较了生成的代码的CIL(确保执行Release版本 – 在Project Properties中选中Optimize Code,它对应于csc.exe上的/optimize开关)。 这就是我得到的(使用VS 2008 – 注意Foo.MaybeFoo()是一种有时返回null的方法,有时候是Foo

GetFooWithIf

  IL_0000: call class Application3.Foo Application3.Foo::MaybeFoo() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: brtrue.s IL_000f IL_0009: newobj instance void Application3.Foo::.ctor() IL_000e: stloc.0 IL_000f: ldloc.0 IL_0010: ret 

GetFooWithCoalescingOperator

  IL_0000: call class Application3.Foo Application3.Foo::MaybeFoo() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: dup IL_0008: brtrue.s IL_0010 IL_000a: pop IL_000b: newobj instance void Application3.Foo::.ctor() IL_0010: stloc.0 IL_0011: ldloc.0 IL_0012: ret 

因此,除了额外的堆栈复制和弹出之外,相同。 如果可以做出可衡量的性能差异,我会专门为了吃它而购买一顶帽子; 因此,请选择您认为具有更好可读性的产品。

(编辑)哦,JITter可能足够聪明,甚至可以摆脱这种差异!

我认为这不是使用null-coalescing运算符。 在阅读代码时,它尽可能简洁明了,代码的意图也很明显。

使用像这样的null-coalescing运算符是正确的,你总是得到一个赋值,但我不担心。 (如果它确实是一个性能问题,你已经知道如何解决它)。

你是对的,因为第一行总是会进行一项任务。 除非代码经常执行,否则我不担心。