2009-11-24 4 views
8
myFoo = myFoo ?? new Foo(); 
대신
if (myFoo == null) myFoo = new Foo(); 

코드의 첫 번째 줄이 항상 할당을 수행한다고 생각하면 맞습니까? 또한 이것은 null-coalescing 연산자의 나쁜 사용입니까?Null Coalescing Operator의 잘못된 사용?

+6

당신은'?? ='연산자에 대한 확실한 인수를 만듭니다. –

+0

@PavelMinaev는이 경우'?| = '연산자와 동일하지 않습니까? 자체 연산자를 보증하기 위해'if (! isset (myFoo)) myFoo = new Foo(); '호출을 대체해야합니다. –

+0

'||'에 부울 값이 필요하기 때문에 동일하지 않습니다. –

답변

19

생성 된 코드의 CIL (csc.exe에있는 /optimize 스위치에 해당하는 프로젝트 속성에서 체크 된 코드 최적화와 릴리스 빌드를 수행해야 함)를 비교했습니다.

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 

따라서,

GetFooWithIf - 이것은 내가 (Foo.MaybeFoo() 때로는 때로는 null을 반환하는 방법, Foo이므로주의 VS 2008 사용) 가지고 무엇을 여분의 top-of-stack-duplication과 pop을 제외하고는 동일합니다. 측정 가능한 성능 차이를 만들 수있는 경우이를 먹기 위해 특별히 모자를 구입합니다. 그러므로 당신이 느끼기 쉬운 가독성과 함께 가십시오.

(편집) 오, 그리고 JITter는 그 차이조차 없애기에 충분히 똑똑 할 것입니다!

+0

이것은'csc.exe/optimize +'로 할 수 있습니까? –

+0

나는 이렇게 생각하여 명확하게 편집했다. – AakashM

+0

나는 Foo가 얼마나 큰지 모르겠다. dup & pop을 실행하는 데 시간이 얼마나 걸립니까? – Gary

4

첫 번째 줄은 항상 지정을한다는 점에서 맞습니다. 코드가 자주 실행되지 않는 한 걱정하지 않아도됩니다.

+0

컴파일러가이를 최적화하지 못하게하려면 어떻게해야합니까? – Timbo

+0

@Timbo : 컴파일러가 어느 정도의 최적화를 할 지에 대한 지식이 너무 많지는 않지만, 'myFoo'가 코드의 다른 곳에서 사용될 것이라는 가정하에 컴파일러가이를 최적화하지 못하게합니다. 그것이 다른 곳에 사용되지 않는다면, 그것은 다른 이야기입니다. –

6

나는 이것이 null-coalescing 연산자의 나쁜 사용이라고 생각하지 않습니다. 코드를 읽을 때 가능한 짧고 간결하며 코드의 의도는 분명합니다.

null-coalescing 연산자를 사용하면 항상 과제를 얻을 수 있지만 걱정하지 않아도됩니다. (그리고 이 실제로 인 경우 성능 문제가 될 수 있으므로 이미 해결 방법을 알고 있습니다.