#1,075 – Operator Precedence Doesn’t Affect Operand Evaluation Order

Rules for operator precedence and associativity determine the order in which the operators within an expression will be evaluated.  Parentheses can also change the order in which the operators are evaluated.

For example:

            // * operator evaluated before +
            int sum1 = 1 + 2 * 3;    // 7

            // + operator evaluated first
            int sum2 = (1 + 2) * 3;  // 9

Operands, however, are evaluated from left-right, regardless of the order of evaluation of the operators. For example, in the code below, the sub-expression Return2() * Return3() is evaluated before adding Return1().  But console output shows us that Return1() was executed first.

        static int Return1()
        {
            Console.WriteLine("1");
            return 1;
        }

        static int Return2()
        {
            Console.WriteLine("2");
            return 2;
        }

        static int Return3()
        {
            Console.WriteLine("3");
            return 3;
        }

        static void Main(string[] args)
        {
            // * operator evaluated before +
            int sum1 = Return1() + Return2() * Return3();    // 7
        }

1075-001

#1,074 – Use Parentheses in Expressions to Make Code More Readable

In the absence of parentheses within an expression, operator precedence and associativity dictate how the expression will be evaluated. Technically, you only need parentheses in the expression if you want the expression to be evaluated differently, relative to the precedence and associativity rules.

If your expression doesn’t require parentheses in order to evaluate correctly, it’s often still a good idea to include them.  The parentheses will typically improve the readability of the expression because they make the evaluation order more clear.

            // This is tough to read
            int i5 = 1 + 10 / 5 * 2 - 12 / 4 + 24 % 5 / 2 * 4;

            // This is a bit better
            i5 = 1 + ((10 / 5) * 2) - (12 / 4) + (((24 % 5) / 2) * 4);

#1,073 – Arithmetic Binary Operators are Left-Associative

All arithmetic binary operators (+, -, *, /, %) are left-associative.  This means that when there are multiple operators having the same precedence, the expression is evaluated from left to right.  Below are some examples.

            // Multiplicative, left-right

            // (10 / 5) * 2 = 4
            // [result would be 1 if right-associative]
            int i = 10 / 5 * 2;

            // (40 % 12) * 2 = 8
            // [result would be 16 if right-associative]
            int i2 = 40 % 12 * 2;

            // Additive, left-right

            // (4 - 3) + 5 = 6
            // [result would be -4 if right-associative]
            int i3 = 4 - 3 + 5;

Note that the multiplicative operators (*, /, %) have a higher precedence than the additive (+, -).  This means that if there are no parentheses, the multiplicative operators are evalated before the arithmetic.

            // 1 + (2 * 3) = 7
            int i4 = 1 + 2 * 3;

            // Equivalent to 1 + ((10 / 5) * 2) = 5
            int i5 = 1 + 10 / 5 * 2;

#28 – Operator Precedence

Each operator has an associated precedence, which indicates the order in which the operators are evaluated when evaluating the  expression.

When an expression has operators of the same precedence, they are evaluated according to their rules of associativity–left to right for all binary expressions, except for assignment and conditional operators, which are right to left.

Here are the C# operators, in order of precedence.  Operators in each group are of equal precedence.

  • Primary:  x.y  f(x)  a[x]  x++  x–  new  typeof  checked  unchecked
  • Unary:  +  –  !  ~  ++x  –x  (T)x
  • Multiplicative:  *  /  %
  • Additive:  +  –
  • Shift:  <<  >>
  • Relational:  <  >  <=  >=  is  as
  • Equality:  ==  !=
  • Logical AND:  &
  • Logical XOR:  ^
  • Logical OR:  |
  • Conditional AND:  &&
  • Conditional OR:  ||
  • Conditional:  ?:
  • Assignment:  =  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=

Precedence can be changed by using parentheses, the inner expressions being evaluated first.

More