简体   繁体   中英

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?

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 A ?? 0 + B ?? 0 A ?? 0 + B ?? 0 is equivalent to A ?? ((0 + B) ?? 0) A ?? ((0 + B) ?? 0) , not (A ?? 0) + (B ?? 0) .

Therefore the action of A ?? 0 + B ?? 0 A ?? 0 + B ?? 0 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 (A + B) ?? 0 . The parentheses are unnecessary in the latter but a good idea given that you were confused about the precedence of + vs ?? .

Without the () in the first statement, you're telling the first ?? operator to return 0 + B if A is null, and the second ?? operator to return 0 if B is null. therefore since the + operator is being used by the ?? operator the statement will only return A. If you set A to null it should return .69

I think more importantly, you should not leave this to the interpretation of anyone, this is a clear example of when you should always use parentheses for readability and the avoidance of doubt. Maintenance is a priority.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM