I am confusing myself with the idea of operator precedence and evaluation direction.
No, you are not. That is frequently confused, yes, but that is not the thing you are confusing because neither precedence nor order of evaluation is relevant to the question of whether the integer is converted to a string, or why it is legal to add an integer to a string.
To first unconfuse you on the point you claim to be confused on, the rules are quite simple:
- expressions are parenthesized according to operator precedence and associativity.
- subexpressions are evaluated in left-to-right order.
That's all you need to know to get it right. Suppose Q() returns an object that has an indexer with a setter, and the other methods all return integers:
Q()[R()] = A() * B() + C() / D();
That is parenthesized according to precedence and associativity:
Q()[R()] = ( ( A() * B() ) + ( C() / D() ) );
And now every subexpression is evaluated left-to-right. Every subexpression, including subexpressions that themselves have subexpressions. So this is equivalent to the program:
var q = Q();
var r = R();
var a = A();
var b = B();
var t1 = a * b;
var c = C();
var d = D();
var t2 = c / d;
var t3 = t1 + t2;
and finally the index setter on q is called with index r and value t3.
Notice that every subexpression to the left is evaluated before every subexpression to the right. A() * B()
is left of C() / D()
, so it happens first.
This has nothing whatsoever to do with your question. Your question is based on a misunderstanding.
I want to know why i is converted to string in the above example, and not actually giving a compilation error
There's your misunderstanding. i
is not being converted to string. It is being converted to object
. Your program is exactly equivalent to:
int i = 10;
string k = "Test";
string t1 = System.String.Concat((object)i, (string)k);
Console.WriteLine(t1);
string t2 = System.String.Concat((string)k, (object)i);
Console.WriteLine(t2);
As you can see, there is no conversion from i
to string in the first place. i
is converted to object via a boxing conversion and then passed to the String.Concat
method. That method then calls object.ToString()
on the boxed integer.
So that deals with the first half of:
I want to know why i is converted to string in the above example, and not actually giving a compilation error
The second half is: why is there no compilation error?
Why should there be a compilation error? The C# specification says that you can add any string to any object, or any object to any string. An int is an object, and therefore you can add it to a string.