Why is it Valid to Concatenate Null Strings but not to Call "null.ToString()"?
Solution 1
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.
Solution 2
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
?).
Solution 3
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
Solution 4
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.
Solution 5
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.
superlogical
Developer from New Zealand! C# .Net/Mono MonoTouch/Mono for Android/Xamarin.Mac Objective-C/iOS Git/Mecurial CSS/SASS MongoDB/Redis/SQL Server/Search/RavenDB/CouchDB/TouchDB Javascript/Node/jQuery/Backbone/CoffeeScript/Angularjs Ruby/Ruby on Rails
Updated on June 05, 2022Comments
-
superlogical almost 2 years
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?
-
superlogical almost 12 yearsThere is no + operator in the String class though.. So is it the compiler translating to String.Concat?
-
Botz3000 almost 12 years@superlogical Yes, that is what the compiler does. So actually, the
+
operator on strings in C# is just syntactic sugar forString.Concat
. -
Botz3000 almost 12 years
String.Empty
is not equal tonull
. It's just treated the same way in some methods likeString.Concat
. For example, if you have a string variable set tonull
, C# won't replace it withString.Empty
if you try to call a method on it. -
Botz3000 almost 12 yearsAlmost.
null
is not treated likeString.Empty
by C#, it's just treated like that inString.Concat
, which is what the C# compiler calls when you add strings."abc" + null
gets translated toString.Concat("abc", null)
, and internally, that method replacesnull
withString.Empty
. The second part is completely correct. -
leppie almost 12 yearsActually, a
AccessViolationException
will be thrown :) -
leppie almost 12 yearsI just did :)
((object)null).ToString()
=>AccessViolation
((object)1 as string).ToString()
=>NullReference
-
Viacheslav Smityukh almost 12 yearsI have got NullReferenceException. DN 4.0
-
leppie almost 12 yearsInteresting. When I put
((object)null).ToString()
inside atry/catch
I getNullReferenceException
too. -
leppie almost 12 yearsDOH, my bad! :*( I was using
((string)null).ToString()
, and that gives the AccessViolation. -
Jochem almost 12 yearsWould this work then? var
wtf = ((String)null).ToString();
I'm working in Java recently where casting null's is possible, has been a while since I worked with C#. -
Lemon almost 12 years@Jochem: You're still trying to call a method on a null object, so I'm guessing no. Think of it as
null.ToString()
vsToString(null)
. -
Jochem almost 12 years@Svish yes, now I think of it again, it is a null object, so you're right, it won't work. It wouldn't in Java neither: null pointer exception. Never mind. Tnx for your reply! [edit: tested it in Java: NullPointerException. With the difference that with cast it compiles, without cast it doesn't].
-
cariseldon almost 12 yearsgenerally there is no reason to intentionally concat or ToString the null keyword. If you need an empty string use string.Empty. if you need to check if a string variable is null you can either use (myString == null) or string.IsNullOrEmpty(myString). Alternatively to transform a null string variable into string.Empty use myNewString = (myString == null ?? string.Empty)
-
Wormbo almost 12 yearsAdding to that: The compiler automatically picks the overload of Concat that makes most sense. Available overloads are 1, 2 or 3 object parameters, 4 object parameters +
__arglist
and aparams
object array version. -
jeroenh almost 12 years@Ieppie except that doesn't throw AccessViolation either (why would it?) - NullReferenceException here.
-
jeroenh almost 12 years@Jochem casting it will make it compile but it will indeed throw a NullReferenceException at runtime
-
Keith Thompson almost 12 yearsSo why does string concatenation work this way? It seems to me this would be likely to mask errors.
-
Ben Mosher almost 12 yearsReally, it's more like
var bob = Plus(Plus(Plus(Plus("abc",null),null),null),"123");
. Operator overloads are static methods at their heart: msdn.microsoft.com/en-us/library/s53ehcz3(v=VS.71).aspx Were they not,var bob = null + "abc";
or especiallystring bob = null + null;
would not be valid. -
IAbstract almost 12 yearsWouldn't the
+
operator be overloaded to use theString.Concat()
function? If so, then it would be possible to treatnull
asString.Empty
, correct? -
Nigel Thorne almost 12 yearsYou're right, I just felt I would be too confusing if I explain it that way.
-
supercat about 9 yearsWhat string array is being modified there? Does
Concat
always create a new array of non-null strings even when given an array of non-null strings, or is something else going on? -
Botz3000 about 9 years@supercat The modified array is a new array, which is then passed to a private helper method. You can look at the code yourself using reflector.