Development Tip

이 두 줄이 같은가요?

yourdevel 2020. 10. 6. 19:32
반응형

이 두 줄이 같은가요? … : 'vs'?? '?


이 두 줄에 차이가 있습니까?

MyName = (s.MyName == null) ? string.Empty : s.MyName

또는

MyName = s.MyName ?? string.Empty

업데이트 : 나는이 주제를 더 깊이 논의하는 블로그 포스트를 썼습니다. http://www.codeducky.org/properties-fields-and-methods-oh-my/


일반적으로 동일한 결과를 반환합니다. 그러나 getter가 첫 번째 예제에서는 두 번 실행되고 두 번째 예제에서는 한 번만 실행 MyName되므로 속성 일 때 눈에 띄는 차이가 발생하는 몇 가지 경우 MyName가 있습니다.

예를 들어, MyName두 번 실행하면 성능 차이가 발생할 수 있습니다 .

string MyName
{
    get 
    {
        Thread.Sleep(10000);
        return "HELLO";
    }
}

또는 상태 저장 인 MyName경우 두 번 실행하면 다른 결과를 얻을 수 있습니다 MyName.

private bool _MyNameHasBeenRead = false;

string MyName
{
    get 
    {
        if(_MyNameHasBeenRead)
                throw new Exception("Can't read MyName twice");
        _MyNameHasBeenRead = true;
        Thread.Sleep(10000);
        return "HELLO";
    }
}

또는 다른 스레드에서 변경 MyNameMyName수있는 경우 두 번 실행하면 다른 결과를 얻을 수 있습니다.

void ChangeMyNameAsync()
{
    //MyName set to null in another thread which makes it 
    //possible for the first example to return null
    Task.Run(() => this.MyName = null);
}

string MyName { get; set; }  

실제 코드가 컴파일되는 방법은 다음과 같습니다. 먼저 삼항식이있는 조각 :

IL_0007:  ldloc.0     // s
IL_0008:  callvirt    s.get_MyName       <-- first call
IL_000D:  brfalse.s   IL_0017
IL_000F:  ldloc.0     // s
IL_0010:  callvirt    s.get_MyName       <-- second call
IL_0015:  br.s        IL_001C
IL_0017:  ldsfld      System.String.Empty
IL_001C:  call        set_MyName

다음은 null-coalescing 연산자가있는 부분입니다.

IL_0007:  ldloc.0     // s
IL_0008:  callvirt    s.get_MyName       <-- only call
IL_000D:  dup         
IL_000E:  brtrue.s    IL_0016
IL_0010:  pop         
IL_0011:  ldsfld      System.String.Empty
IL_0016:  call        s.set_MyName

보시다시피 삼항 연산자에 대한 컴파일 된 코드는 속성 값을 얻기 위해 두 번의 호출을 수행하는 반면 null 통합 연산자는 1 만 수행합니다.


속성이 단순한 getter 이상인 경우 첫 번째 항목에 대해 null이 아닌 경우 함수를 두 번 실행할 수 있습니다.

속성이 상태 저장 객체에있는 경우 속성에 대한 두 번째 호출은 다른 결과를 반환 할 수 있습니다.

class MyClass
{
    private IEnumerator<string> _next = Next();

    public MyClass()
    {
        this._next.MoveNext();
    }

    public string MyName
    {
        get
        {
            var n = this._next.Current;
            this._next.MoveNext();
            return n;
        }
    }


    public static IEnumerator<string> Next()
    {
        yield return "foo";
        yield return "bar";
    }
}

또한 문자열이 아닌 경우 클래스는 삼항 연산자와 다른 작업을 수행하기 위해 ==를 오버로드 할 수 있습니다. 삼항 연산자가 오버로드 될 수 있다고 생각하지 않습니다.


The only difference is whether you evaluate s.MyName twice or once. The first will do it twice in the case that s.MyName is not null, the second will only ever evaluate it once.

In most cases, this difference doesn't matter, and I'd go with the second because it's more clear and concise.


Yes, both are the same, and it is the null-coalescing operator.

It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.

If we talk about efficiency then

string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;

If I use a dissembler then I can see that the first statement needs 19 statements to be executed by the compiler whereas the second statement required only 12 statements to be executed.


Yes, they do the same. ?? is shorthand for checking for null.


They accomplish the same task.

Only difference would be readability as to whether your coworkers or whomever is reading the code understands the syntax.

EDIT: Additionally the first option can evaluate the property MyName twice.


No. Both are doing the same thing. Second one is efficient. Which returns the actual value if it is not null. Else the right-hand side value will be returned.

Refer this http://msdn.microsoft.com/en-us/library/ms173224.aspx

Hope this helps.

참고URL : https://stackoverflow.com/questions/21052437/are-these-two-lines-the-same-vs

반응형