Are these two lines the same, '? … :' vs '??'?

前端 未结 7 2106
醉梦人生
醉梦人生 2021-01-30 19:28

Is there a difference between these two lines?

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

or

MyName = s.MyName ?? st         


        
7条回答
  •  甜味超标
    2021-01-30 20:17

    UPDATE: I wrote a blog post that discusses this topic in more depth. http://www.codeducky.org/properties-fields-and-methods-oh-my/


    Generally they will return the same result. However, there are a few cases where you will experience noticeable differences when MyName is a property because the MyName getter will be executed twice in the first example and only once in the second example.

    For example, you may experience performance differences from executing MyName twice:

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

    Or you may get different results from executing MyName twice if MyName is stateful:

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

    Or you may get different results from executing MyName twice if MyName can be changed on a different thread:

    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; }  
    

    Here's how the actual code is compiled. First the piece with the ternary expression:

    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
    

    and here is the piece with the null-coalescing operator:

    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
    

    As you can see the compiled code for the ternary operator will make two calls to get the property value, whereas the null-coalescing operator will only do 1.

提交回复
热议问题