3

Possible Duplicate:
C#: Why is adding null to a string legal?

Here is the valid C# code:

var samsung= "xyz" + null + null + null + null + "890";  // xyz890

And this is the invalid C# code:

var iphone= null.ToString(); // compiler error

Why and how is the first statement valid and second is invalid ?

Community
  • 1
  • 1
HereToLearn_
  • 1,150
  • 4
  • 26
  • 47
  • 1
    You cant change `nothing`(here which is null) – Mr_Green Nov 15 '12 at 15:56
  • 1
    Wonder if the null additions are removed by the compiler? Anyone know? – Grant H. Nov 15 '12 at 15:57
  • 2
    @GrantH. if they are null constants then yes. In fact the whole expression is simplified to `"xyz890"` in IL. – D Stanley Nov 15 '12 at 15:59
  • 2
    @GrantH. They are, but technically it won't change the result, just the performance. If it didn't evaluate it to a single constant at compile time (you could trivially change this to prevent it from being able to do that) then it would still work, and if it couldn't run it at runtime then it wouldn't be able to optimize it at compile time. In other words, the compile time optimization doesn't change the explanation of why this does or doesn't work. – Servy Nov 15 '12 at 16:09

9 Answers9

4

The + operator is used to concatenate strings, and since null is an instance of the string class it can be used as an argument to the operator. "xyz" + null ends up returning the string "xyz", so this process is just repeated until you actually add "890".

While null can be used as a string object for an argument to a method, you cannot actually call methods on it because there's nothing to process the method call.

Think of methods as a way for an object to process an external request and things make a bit more sense. You can send a request to an object with null as an argument for what to process, but you can't actually ask null to process something.

Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
  • This is really good explaination too. Thankss ! – HereToLearn_ Nov 15 '12 at 16:34
  • _"`null` is an instance of the string class ..."_ No, it's not an instance in any way. It's an expression which can be interpreted, in some cases, as having type `string`. In this case you can also interprete it as being `(object)null`; the result is the same. But a null reference is no instance, it is lack of instance. – Jeppe Stig Nielsen Nov 15 '12 at 16:55
1

The C# compiler thinks of null in concatenations as an empty string.

 var samsung= "xyz" + null + null + null + null + "890";

equals

 var samsung= "xyz" + ""+ ""+ ""+ ""+ "890";

When you try to call null.toString() you are essentially trying to call a method on a null object, which (if it compiled) would always cause a NullReferenceException.

MAV
  • 7,260
  • 4
  • 30
  • 47
1

With the first line, you are concatinating strings. null is nothing, so essentially you are getting xyz890. It's like doing 1+0+0+0+4 But with your second, you're call ToString() on a null. null is nothing, so there's nothing there to call ToString() on. You're attempting to call a method on an non-initialized variable.

PiousVenom
  • 6,888
  • 11
  • 47
  • 86
  • Ohhh makes sense to me now! Thanks a lot guys :-) My question is answered. – HereToLearn_ Nov 15 '12 at 16:05
  • @user1688826 If your question is answered, you should accept an answer – swiftgp Nov 15 '12 at 16:16
  • 1
    While this isn't wrong, you don't actually explain why you can concat null with a string using `operator +`, you just say *that* you can. Running his code already told him that much... – Servy Nov 15 '12 at 16:18
  • @Servy: I gave the example of `1+0+0+0+4` as an example. Was hoping it was the concept would be understood. – PiousVenom Nov 15 '12 at 16:43
  • @TyrionLannister The *concept* is irrelivant here. Logically it might make sense for null concatted with "abc" to be abc, but note that `null.Concat("abc")` results in a null pointer exception. What makes that different from `null + "abc"` which works as expected without error? That's what your answer should explain to actually answer the question. Again, it's not wrong, it just skips over the part of the question that's actually important. – Servy Nov 15 '12 at 16:47
1

Since string is a reference type, null can be implicitly converted to string. And in first case sequence of + operators just is transformed to String.Concat(obj1, obj2, obj3, ...)

To make your code compile you can call Convert.ToString:

var iphone = Convert.ToString(null);
tukaef
  • 9,074
  • 4
  • 29
  • 45
1

You can think of the + operator as a global static function like so:

+(string leftHandSide, string rightHandSide) {
  if (leftHandSide == null)
     leftHandSide = string.Empty;
  if (rightHandSide == null)
     rightHandSide = string.Empty;
  string returnValue;

  // concatenate string

  return returnValue;
}

Since this string concatenation method is static it does not require an instance to call it, it handles the null values. However when you try to call ToString on null there is no instance of an object so there is no ToString mehthod to call, hence the exception.

Charles Lambert
  • 5,042
  • 26
  • 47
1

This is by design. You could read the C# Language Specification. Quote:

String concatenation:

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);

These overloads of the binary + operator perform string concatenation. 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.

[...]

So, as others have said, think of + as a kind of method that takes in two arguments and is OK with one or both of them being null.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

Because you can't call a method on a null reference in any case, so the compiler doesn't allow it. In your first case, the compiler will pre-compile the string constant to "xyz890" so it is a legal assignment.

In general, the + operator for string compiles to String.Concat(s1, s2, ...) which supports null arguments.

To be more precise on the second case, the actual problem isn't that it's a null pointer, it's that there is no type to bind the method to. As pointed out in other comments, you can cast null to any reference type and it compiles just fine:

((string)null).ToString();   // compiles, but fails at run-time.
D Stanley
  • 149,601
  • 11
  • 178
  • 240
0

The + operator will be translated to a static function that looks much like:

public static string Concat(string first, string second) {...}

Passing null as a parameter to a function isn't a problem; it gets passed just fine. That function happens to check that neither of the parameters are null before concatting them; if any of the parameters are null they are treated as empty strings so as to not cause exceptions. The key point here is that no instance members of the strings are called until they are first null checked by this function.

As for null.ToString() calling an instance function on anything that evaluates to null at compile time results in an exception. This is the very definition of that case.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • 1
    Good explanation. Just a technical detail: Writing `null.ToString()` gives the compile-time error: _CS0023: Operator '.' cannot be applied to operand of type ''_ However, if you help a little with the type, as in `((string)null).ToString()`, it will compile fine and you get your `NullReferenceException` run-time. – Jeppe Stig Nielsen Nov 15 '12 at 17:05
0

If you look at the IL you'll see that the compiler is smart enough to just drop the null values and creates a concatenated string. As mentioned earlier you can't do a null.ToString(); you can do string.Empty or assign a string to be null.

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] string samsung)
  IL_0000:  nop
  IL_0001:  ldstr      "xyz890"        //null has been removed by compiler.  
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method Program::Main 

EDIT
Expand on Nielson's comment. As null represents an nil reference it might be fair to say that the way string concat is handled is C# permits such as operation. I'd fathom it uses byte array building which would omit the null values, thus simply making it appear as if it's concating null.

Samir Banjanovic
  • 400
  • 1
  • 4
  • 16
  • I think the Original Poster is asking **why** it's legal. It's a technical detail that the compiler performs the complete operation (five plusses) by itself _compile-time_ and only emits the correct "sum" in its IL output. – Jeppe Stig Nielsen Nov 15 '12 at 16:48