2009-11-24 2 views
8
myFoo = myFoo ?? new Foo(); 

вместоПлохое использование оператора Null Coalescing?

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

Я правильно думать, что первая строка кода всегда будет выполнять задание? Кроме того, это плохое использование оператора нуль-коалесценции?

+6

Вы делаете убедительный аргумент для оператора '?? =' :) –

+0

@PavelMinaev в этом случае, что не совпадает с оператором '|| ='? Он должен был бы заменить вызов 'if (! Isset (myFoo)) myFoo = new Foo();', чтобы гарантировать свой собственный оператор. –

+0

Это не идентично, так как '||' требует булевского значения. –

ответ

19

Я сравнил 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 может быть достаточно умным, чтобы избавиться от этой разницы!

+0

Это с 'csc.exe/optimize +'? –

+0

Я так думаю, отредактирован, чтобы уточнить. – AakashM

+0

Я не знаю, насколько велик Foo. Размер влияет на время запуска dup & pop? – Gary

4

Вы правы в том, что первая строка всегда будет выполнять задание. Я бы не стал беспокоиться об этом, если код не выполняется очень часто.

+0

Что должно остановить компилятор от его оптимизации? – Timbo

+0

@Timbo: Я не слишком осведомлен о том, какие оптимизаторы могут или не могут быть выполнены компилятором, но я предполагаю, что 'myFoo' будет использоваться в другом месте кода и что это не позволит компилятору оптимизировать его. Если он не используется в другом месте, это совсем другая история. –

6

Я не думаю, что это плохое использование оператора нуль-коалесценции. При чтении кода он максимально короткий и краткий, и цель кода очевидна.

Правильно, что с использованием оператора нуль-коалесцирования, подобного этому, вы всегда будете получать задание, но я бы не стал беспокоиться об этом. (И если это действительно оказывается проблемой производительности, вы уже знаете, как это исправить).