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

c#

Solution

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.

Problem

Is there a difference between these two lines? ``` MyName = (s.MyName == null) ? string.Empty : s.MyName ``` or ``` MyName = s.MyName ?? string.Empty ```

Original source