8
myFoo = myFoo ?? new Foo();

代替

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

我认为第一行代码将始终执行分配是否正确?此外,这是对 null-coalescing 运算符的错误使用吗?

4

3 回答 3

19

我比较了生成代码的 CIL(确保进行发布构建 - 在项目属性中选中优化代码,这对应于打开的/optimize开关csc.exe)。这就是我得到的(使用 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 可能足够聪明,甚至可以消除这种差异!

于 2009-11-24T18:29:33.557 回答
6

我不认为这是对空合并运算符的不好使用。阅读代码时,尽量简短简洁,代码意图明显。

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

于 2009-11-24T18:08:10.027 回答
4

您是正确的,第一行将始终进行分配。除非代码经常执行,否则我不会担心这一点。

于 2009-11-24T18:07:36.517 回答