superlogical
superlogical

Reputation: 14950

Why is it Valid to Concatenate Null Strings but not to Call "null.ToString()"?

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

Answers (11)

Matt
Matt

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

Pranay Rana
Pranay Rana

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 returns null, 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

g.pickardou
g.pickardou

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

Viacheslav Smityukh
Viacheslav Smityukh

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

Saeed Neamati
Saeed Neamati

Reputation: 35822

I guess because it's a literal which doesn't refer to any object. ToString() needs an object.

Upvotes: 3

Talha
Talha

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

Nigel Thorne
Nigel Thorne

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

supercat
supercat

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

Botz3000
Botz3000

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

Franky
Franky

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

Thorsten Dittmar
Thorsten Dittmar

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

Related Questions