Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# addition with nullable decimals and precedence of ?? operator

Assume a C# program with two nullable decimal properties A and B. The following addition returns the value of A only: var result = A ?? 0 + B ?? 0; The correct usage is: var result = (A ?? 0) + (B ?? 0);

Sample console program:

class Program
{
    static void Main(string[] args)
    {
        A = (decimal)0.11;
        B = (decimal)0.69;

        NullableDecimalAddition();

        Console.ReadLine();
    }

    public static decimal? A { get; set; }
    public static decimal? B { get; set; }

    private static void NullableDecimalAddition()
    {
        decimal result1 = A ?? 0 + B ?? 0;
        decimal result2 = (A ?? 0) + (B ?? 0);
        Console.WriteLine("result1: " + result1);  // = 0.11
        Console.WriteLine("result2: " + result2);  // = 0.80
    }
}

My question is what happens during the calculation with result1. How is the precedence of the + and ?? operators?

like image 372
Nicolo Avatar asked Jul 14 '13 05:07

Nicolo


1 Answers

tinstaafl's answer is correct. To expand upon it:

The ?? operator is right associative and the + operator is higher precedence. Therefore A ?? 0 + B ?? 0 is equivalent to A ?? ((0 + B) ?? 0), not (A ?? 0) + (B ?? 0).

Therefore the action of A ?? 0 + B ?? 0 is:

  • Compute A, which you state is of type nullable decimal. If it is non-null, obtain its decimal value as the result. We are now done; B is never computed.
  • The zero has already been converted to decimal by the compiler and its null check for the lifted arithmetic is elided. (See my series of articles on how nullable arithmetic is optimized by the compiler for details.)
  • B is computed and checked for null. If it is null then the result of the addition is null; if not then the result of the addition is a nullable decimal.
  • The result of the addition is now checked for null. If it is null then the result is zero (again, already converted to decimal). If it is not null then its value is fetched and that becomes the result.

This is not your intended action; you can obtain your intended action with (A ?? 0) + (B ?? 0). If you intended by contrast to mean "use zero if either side is null" then you could use (A + B) ?? 0. The parentheses are unnecessary in the latter but a good idea given that you were confused about the precedence of + vs ??.

like image 159
Eric Lippert Avatar answered Sep 26 '22 18:09

Eric Lippert