David Vogel
David Vogel

Reputation: 465

Is using the null-coalescing operator in C# always redunant if defaulting to null?

In C# is

x = y ?? null;

always equivalent to

x = y;

if both x and y are nullable types?

I can't think of a reason why the first line of code would ever be needed over the second.

Upvotes: 2

Views: 201

Answers (3)

BradleyDotNET
BradleyDotNET

Reputation: 61369

Yes, writing the line

x = y ?? null;

Seems silly, since the expression will return null if y is null (so basically returning y) and y otherwise.

Remember that the null-coalescing operator is functionally the same as writing:

x = y != null ? y : <whatever operand>

Or, of course (for those not familiar with the ternary operator):

if (y != null)
   x = y;
else
   x = <whatever operand>;

In either case, using the null as the second argument has no utility whatsoever. You might as well just assign the variable, as noted in your post.

Upvotes: 4

Tim S.
Tim S.

Reputation: 56556

Yes, it is equivalent. Even if you have a DynamicObject that's trying to provide specific behavior for a Coalesce operation, TryBinaryOperation is never entered. The following code does not print anything.

void Main()
{
    dynamic y = new MyDyn(); // or with this null
    dynamic z = new MyDyn();
    object x = y ?? z;
}
public class MyDyn : DynamicObject
{
    public override bool TryBinaryOperation(
        BinaryOperationBinder binder,
        Object arg,
        out Object result
    )
    {
        Console.WriteLine("Hello world!");
        if (binder.Operation == ExpressionType.Coalesce)
        {
            result = 3;
            return true;
        }
        result = null;
        return true;
    }
}

Upvotes: 1

Steven Wexler
Steven Wexler

Reputation: 17299

Yes, they are functionally the same. It doesn't make sense to write

x = y ?? null over x = y

If you're curious, the IL code generated by x = y ?? null is more complex than the IL code generated from x = y.

x = y ?? null

IL_0014:  ldloc.0     // y
IL_0015:  stloc.2     // CS$0$0000
IL_0016:  ldloca.s    02 // CS$0$0000
IL_0018:  call        System.Nullable<System.Int32>.get_HasValue
IL_001D:  brtrue.s    IL_002A
IL_001F:  ldloca.s    03 // CS$0$0001
IL_0021:  initobj     System.Nullable<System.Int32>
IL_0027:  ldloc.3     // CS$0$0001
IL_0028:  br.s        IL_0036
IL_002A:  ldloca.s    02 // CS$0$0000
IL_002C:  call        System.Nullable<System.Int32>.GetValueOrDefault
IL_0031:  newobj      System.Nullable<System.Int32>..ctor
IL_0036:  nop         
IL_0037:  stloc.1     // x

x = y

IL_0009:  ldloc.0     // y
IL_000A:  stloc.1     // x

Upvotes: 2

Related Questions