Beware operator precedence

In That’s just wrong!, I described some … unexpected results that occur due to the string concatenation optimization that the C# compiler performs. It seems a bit wonky to me, but perhaps people who do a lot of string concatenation find it useful.

Today I ran across a new one, thank to Eric Lippert’s blog post, A string Concatenation puzzle.

Based on my previous blog post, you know that this code:

    string s = "";
    s = s + 5 + 5;

Will result in the string s containing the value "55". Or, after the compiler’s optimizations: string.Concat(s, 5, 5)

So what would you expect as the result of this code?

    string s = "";
    s += 5 + 5;

How about "10"? Ouch. Operator precedence.

You see, writing s += expression is the same as writing s = s + (expression), so what you end up with is s + (5 + 5). After the compiler is done with its optimization magic, you have s = string.Concat(s, 10).

That seems wonky because in numerical calculations (a + b) + c is the same as a + (b + c). That’s true for strings, as well, but not true when you combine numerical operations and string concatenation. Remember, when you see s + (5 + 5), the compiler generates code to add the two numbers in parentheses and passes that value to String.Concat.

This kind of thing isn’t limited to strings, by the way. You can get yourself in trouble with numeric calculations, too. Consider:

    int a = 2;
    int b = 3;
    b = b + a << 1;  // result = 10

    // or, replace the above with
    b += a << 1;     // result = 7

Operator precedence again. Operator << has lower precedence than operator +. So b = b + a << 1 is evaluated as (b + a) << 1. The other is evaluated as b + (a << 1). Oddly enough, I saw this one trip somebody up the other day.

I think the key here is to understand that a += expression is equivalent to a = a + (expression). The entire expression is evaluated before the addition. Failure to understand that can lead to some rather mystifying results.