Я сравнил CIL сгенерированного кода (убедитесь, что вы сделали сборку Release - с кодом оптимизации, отмеченным в свойствах проекта, который соответствует переключателю на 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
Таким образом, то же самое, за исключением дополнительного дублирования и pop-up-stack-duplication. Если это можно сделать, чтобы измерить разницу в производительности, я куплю шляпу специально для ее съедения; поэтому, идите с тем, который, по вашему мнению, обеспечивает лучшую читаемость.
(править) oh, и JITter может быть достаточно умным, чтобы избавиться от этой разницы!
Вы делаете убедительный аргумент для оператора '?? =' :) –
@PavelMinaev в этом случае, что не совпадает с оператором '|| ='? Он должен был бы заменить вызов 'if (! Isset (myFoo)) myFoo = new Foo();', чтобы гарантировать свой собственный оператор. –
Это не идентично, так как '||' требует булевского значения. –