Reputation: 14950
This is valid C# code
var bob = "abc" + null + null + null + "123"; // abc123
This is not valid C# code
var wtf = null.ToString(); // compiler error
Why is the first statement valid?
Upvotes: 137
Views: 28221
Reputation: 27001
Someone said in this discussion thread that you can't make a string out of nothing. (which is a nice phrase as I think). But yes - you can :-), as the following example shows:
var x = null + (string)null;
var wtf = x.ToString();
works fine and does not throw an exception at all. The only difference is that you need to cast one of the nulls into a string - if you remove the (string) cast, then the example still compiles, but throws a run-time exception: "Operator '+' is ambiguous on operands of type '<null>' and '<null>'".
N.B. In the code example above, the value of x
is not null as you might expect, it is actually an empty string after you have casted one of the operands into a string.
Slightly different is var a = ((string)null).ToString();
- which compiles but will throw a NullReferenceException. In this case the exception is thrown because the .
operator isn't allowed on null values. Using ?.
would work here (but ToString isn't executed in this case). The compiler will correctly "create" the variable a
as a string.
Another interesting fact is that in C# / .NET the way null
is treated is not always the same if you regard different data types. For example:
int? x = 1; // string x = "1";
x = x + null + null;
Console.WriteLine((x==null) ? "<null>" : x.ToString());
Regard the 1st line of the code snippet: If x
is a nullable integer variable (i.e. int?
) containing value 1
, then you're getting the result <null>
back. If it is a string (as shown in the comment) with value "1"
, then you're getting "1"
back rather than <null>
.
N.B. Also interesting: If you're using var x = 1;
for the first line, then you're getting a runtime error. Why? Because the assignment will turn the variable x
into the datatype int
, which is not nullable. The compiler does not assume int?
here, and hence fails in the 2nd line where null
is added.
Upvotes: 2
Reputation: 176896
The reason for first one working:
From MSDN:
In string concatenation operations,the C# compiler treats a null string the same as an empty string, but it does not convert the value of the original null string.
More information on the + binary operator:
The binary + operator performs string concatenation when one or both operands are of type string.
If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual
ToString
method inherited from type object.If
ToString
returnsnull
, an empty string is substituted.
The reason of the error in second is:
null (C# Reference) - The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables.
Upvotes: 174
Reputation: 35873
As general: It may or may not valid accepting null as a parameter depending on specification, but it is always invalid to call a method on null.
That's and other topic why the + operator's operands can be null in case of strings. This is kinda VB thing (sorry guys) to make programmers life easier, or supposing the programmer can not deal with nulls. I completely disagree this specification. 'unknown' + 'anything' should be still 'unknown'...
Upvotes: 0
Reputation: 5843
The first sample will be translated into:
var bob = String.Concat("abc123", null, null, null, "abs123");
The Concat
method checks input and translate null as an empty string
The second sample will be translated into:
var wtf = ((object)null).ToString();
So a null
reference exception will be generated here
Upvotes: 30
Reputation: 35822
I guess because it's a literal which doesn't refer to any object. ToString()
needs an object
.
Upvotes: 3
Reputation: 19252
The first part of your code is just treated like that in String.Concat
,
which is what the C# compiler calls when you add strings. "abc" + null
gets translated to String.Concat("abc", null)
,
and internally, that method replaces null
with String.Empty
. So, that's why your first part of code does not throw any exception. it is just like
var bob = "abc" + string.Empty + string.Empty + string.Empty + "123"; //abc123
And in 2nd part of your code throws exception because 'null' is not an object, the null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables.
And 'ToString()
' is a method that can be called by an instance of an object but not any literal.
Upvotes: 12
Reputation: 21548
'+'
is an infix operator. Like any operator it is really calling a method. You could imagine a the non-infix version "wow".Plus(null) == "wow"
The implementer has decided on something like this...
class String
{
...
String Plus(ending)
{
if(ending == null) return this;
...
}
}
So.. your example becomes
var bob = "abc".Plus(null).Plus(null).Plus(null).Plus("123"); // abc123
which is the same as
var bob = "abc".Plus("123"); // abc123
At no point does null become a string. So null.ToString()
is no different that null.VoteMyAnswer()
. ;)
Upvotes: 5
Reputation: 81159
In the COM framework which preceded .net, it was necessary for any routine which received a string to free it when it was done with it. Because it was very common for empty strings to be passed into and out of routines, and because attempting to "free" a null pointer was defined as a legitimate do-nothing operation, Microsoft decided to have a null string pointer represent an empty string.
To allow for some compatibility with COM, many routines in .net will interpret a null object as a legal representation as an empty string. With a couple of slight changes .net and its languages (most notably allowing instance members to indicate "do not invoke as virtual"), Microsoft could have made null
objects of declared type String behave even more like empty strings. If Microsoft had done that, it would have also had to make Nullable<T>
work somewhat differently (so as to allow Nullable<String>
--something they should IMHO have done anyway) and/or define a NullableString
type which would be mostly interchangeable with String
, but which would not regard a null
as a valid empty string.
As it is, there are some contexts in which a null
will be regarded as a legitimate empty string and others in which it won't. Not a terribly helpful situation, but one which programmers should be aware of. In general, expressions of the form stringValue.someMember
will fail if stringValue
is null
, but most framework methods and operators which accept strings as parameters will regard null
as an empty string.
Upvotes: 9
Reputation: 39610
Because the +
operator in C# internally translates to String.Concat
, which is a static method. And this method happens to treat null
like an empty string. If you look at the source of String.Concat
in Reflector, you'll see it:
// while looping through the parameters
strArray[i] = (str == null) ? Empty : str;
// then concatenate that string array
(MSDN mentions it, too: http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx)
On the other hand, ToString()
is an instance method, which you cannot call on null
(what type should be used for null
?).
Upvotes: 112
Reputation: 651
Because there is no difference between string.Empty
and null
when you concat strings.
You can pass null into string.Format
as well. But you are trying to call a method on null
, which would always result in a NullReferenceException
and therefore generates a compiler error.
If for some reason you really want to do it, you could write an extension method, that checks for null
and then returns string.Empty
. But an extension like that should only be used when absolutly necessary (in my opinion).
Upvotes: 1
Reputation: 56697
Adding null
to a string is simply ignored. null
(in your second example) isn't an instance of any object, so it doesn't even have a ToString()
method. It's just a literal.
Upvotes: 2