Since true
is not a string type, how is null + true
a string ?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
What is the reason behind this?
Since true
is not a string type, how is null + true
a string ?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
What is the reason behind this?
The reason for this is convenience (concatenating strings is a common task).
As BoltClock said, the '+' operator is defined on numeric types, strings, and can be defined for our own types as well (operator overloading).
If there is not an overloaded '+' operator on the argument's types and they are not numeric types, the compiler defaults to string concatenation.
The compiler inserts a call to
String.Concat(...)
when you concatenate using '+', and the implementation of Concat calls ToString on each object passed into it.The reason why is because once you introduce the
+
then the C# operator binding rules come into play. It will consider the set of+
operators available and select the best overload. One of those operators is the followingThis overload is compatible with the argument types in the expression
null + true
. Hence it is selected as the operator and is evaluated as essentially((string)null) + true
which evaluates to the value"True"
.Section 7.7.4 of the C# language spec contains the details around this resolution .
null
will be cast to null string, and there is implicit converter from bool to string so thetrue
will be cast to string and then,+
operator will be applied: it's like: string str = "" + true.ToString();if you check it with Ildasm:
string str = null + true;
it's as bellow:
The compiler goes out hunting for an operator+() that can take a null argument first. None of the standard value types qualify, null is not a valid value for them. The one and only match is System.String.operator+(), there's no ambiguity.
The 2nd argument of that operator is also a string. That goes kapooey, cannot implicitly convert bool to string.
Bizarre as this may seem, it's simply following the rules from the C# language spec.
From section 7.3.4:
So, let's walk through this in turn.
X is the null type here - or not a type at all, if you want to think of it that way. It's not providing any candidates. Y is
bool
, which doesn't provide any user-defined+
operators. So the first step finds no user-defined operators.The compiler then moves on to the second bullet point, looking through the predefined binary operator + implementations and their lifted forms. These are listing in section 7.8.4 of the spec.
If you look through those predefined operators, the only one which is applicable is
string operator +(string x, object y)
. So the candidate set has a single entry. That makes the final bullet point very simple... overload resolution picks that operator, giving an overall expression type ofstring
.One interesting point is that this will occur even if there are other user-defined operators available on unmentioned types. For example:
That's fine, but it's not used for a null literal, because the compiler doesn't know to look in
Foo
. It only knows to considerstring
because it's a predefined operator explicitly listed in the spec. (In fact, it's not an operator defined by the string type... 1) That means that this will fail to compile:Other second-operand types will use some other operators, of course:
1 You may be wondering why there isn't a string + operator. It's a reasonable question, and I'm only guessing at the answer, but consider this expression:
If
string
had no special-casing in the C# compiler, this would end up as effectively:So that's created two unnecessary intermediate strings. However, because there's special support within the compiler, it's actually able to compile the above as:
which can create just a single string of exactly the right length, copying all the data exactly once. Nice.
Crazy?? No, there must be a reason behind it.
Someone call
Eric Lippert
...