2009-11-24 9 views
8
myFoo = myFoo ?? new Foo(); 
の代わりに

ヌル合体オペレータの悪い使用ですか?

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

コードの最初の行が常に代入を実行すると思いますか?また、これはヌル合体演算子の悪い使用ですか?

+6

'?? ='演算子の説得力のある引数を作る: –

+0

この場合、@PavelMinaevは '|| ='演算子と同じではないのですか?それ自身の演算子を保証するために 'if(!isset(myFoo))myFoo = new Foo();'の呼び出しを置き換える必要があります。 –

+0

'||'はブール値を必要とするので、同じではありません。 –

答えて

19

私は、生成されたコードのCILを比較しました(csc.exe/optimizeスイッチに対応するプロジェクトのプロパティでリリースビルド - コードの最適化を確認してください)を比較しました。これは私が(VS 2008を使用して - 時々FooFoo.MaybeFoo()は時々nullを返すメソッドであることに注意してください)得たものである

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は、その違いをなくすには十分に賢いかもしれない!

+0

これは 'csc.exe/optimize +'でですか? –

+0

私はそう思って、明確にするために編集しました。 – AakashM

+0

フーの本当の大きさは分かりません。 dupとpopを実行する時間に影響しますか? – Gary

4

最初の行が常に割り当てを行うという点では正しいです。コードが非常に頻繁に実行されない限り、私は心配しません。

+0

コンパイラが最適化をやめないようにするには? – Timbo

+0

@Timbo:私はコンパイラがどのような最適化をしているのか、そうしていないのかよく知っているわけではありませんが、私は 'myFoo'がコードのどこかで使用され、コンパイラが最適化できないことを前提にしています。他の場所で使用されていない場合は、別の話です。 –

6

私はこれをヌル合体演算子の悪い使用とは考えていません。コードを読むとき、できるだけ簡潔で簡潔であり、コードの意図は明らかです。

このようにヌル合体演算子を使用すると、常に代入が行われますが、それについては心配しません。 (の場合、実際にはがパフォーマンスの問題であることが判明しています。

関連する問題