myFoo = myFoo ?? new Foo();
대신
if (myFoo == null) myFoo = new Foo();
코드의 첫 번째 줄이 항상 할당을 수행한다고 생각하면 맞습니까? 또한 이것은 null-coalescing 연산자의 나쁜 사용입니까?Null Coalescing Operator의 잘못된 사용?
myFoo = myFoo ?? new Foo();
대신
if (myFoo == null) myFoo = new Foo();
코드의 첫 번째 줄이 항상 할당을 수행한다고 생각하면 맞습니까? 또한 이것은 null-coalescing 연산자의 나쁜 사용입니까?Null Coalescing Operator의 잘못된 사용?
생성 된 코드의 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는 그 차이조차 없애기에 충분히 똑똑 할 것입니다!
첫 번째 줄은 항상 지정을한다는 점에서 맞습니다. 코드가 자주 실행되지 않는 한 걱정하지 않아도됩니다.
컴파일러가이를 최적화하지 못하게하려면 어떻게해야합니까? – Timbo
@Timbo : 컴파일러가 어느 정도의 최적화를 할 지에 대한 지식이 너무 많지는 않지만, 'myFoo'가 코드의 다른 곳에서 사용될 것이라는 가정하에 컴파일러가이를 최적화하지 못하게합니다. 그것이 다른 곳에 사용되지 않는다면, 그것은 다른 이야기입니다. –
나는 이것이 null-coalescing 연산자의 나쁜 사용이라고 생각하지 않습니다. 코드를 읽을 때 가능한 짧고 간결하며 코드의 의도는 분명합니다.
null-coalescing 연산자를 사용하면 항상 과제를 얻을 수 있지만 걱정하지 않아도됩니다. (그리고 이 실제로 인 경우 성능 문제가 될 수 있으므로 이미 해결 방법을 알고 있습니다.
당신은'?? ='연산자에 대한 확실한 인수를 만듭니다. –
@PavelMinaev는이 경우'?| = '연산자와 동일하지 않습니까? 자체 연산자를 보증하기 위해'if (! isset (myFoo)) myFoo = new Foo(); '호출을 대체해야합니다. –
'||'에 부울 값이 필요하기 때문에 동일하지 않습니다. –