This question already has an answer here:
-
Why is it Valid to Concatenate Null Strings but not to Call “null.ToString()”?
11 answers
I was fiddling around in C# when I came across this weird behavior in .Net programming.
I have written this code:
static void Main(string[] args)
{
string xyz = null;
xyz += xyz;
TestNullFunc(xyz);
Console.WriteLine(xyz);
Console.Read();
}
static void TestNullFunc(string abc)
{
if (abc == null)
{
Console.WriteLine("meow THERE ! ");
}
else
{
Console.WriteLine("No Meow ");
}
}
I got the output as No meow
, which means the string is not null
. How is this possible? Why does adding two null
strings, result in a non-null
string?
On debugging when I check the value of xyz
after adding it to itself, its value is ""
(no characters).
From MSDN:
In string concatenation operations, the C# compiler treats a null string the same as an empty string,
Even though xyz
is null, calling the += operator (which is converted to a call to the + operator (*)) on it does not throw a NullReferenceException
because it's a static method. In pseudo code:
xyz = String.+(null, null);
The implementation will then interpret this as if it was
xyz = String.+("", "");
(*) Section §7.17.2 of the C# specification:
An operation of the form x op= y is processed by applying binary operator overload resolution (§7.3.4) as if the operation was written x op y.
When you use the +=
operator, you are actually calling the string.Concat method, that, as stated in the documentation:
The method concatenates str0 and str1; it does not add any delimiters.
An Empty string is used in place of any null argument.
In fact this code:
string xyz = null;
xyz += xyz;
will be compiled in:
IL_0000: ldnull
IL_0001: stloc.0 // xyz
IL_0002: ldloc.0 // xyz
IL_0003: ldloc.0 // xyz
IL_0004: call System.String.Concat
IL_0009: stloc.0 // xyz
As stated, the reason why is that concatenating null is taken to be the same as concatenating an empty string.
It's worth considering why this behaviour is useful.
Normally, there are two sensible things we can do with an binary operator when one of the operands is null:
- The result is null.
- The operation is a no-op, and we're left with the other operand.
It makes sense for instance, that ((int?)null) + 3
results in null
, and generally either this will be the most useful result, or one we will consciously guard against (that is, we'll add code to catch the null case explicitly).
But there are two reasons to not do this with string concatenation.
The first is to consider, that since concatenation means not an arithmetic calculation, but sticking two things together, then what is the most reasonable result of sticking null onto the beginning or end of something? It's easy to make the case that this should do nothing, rather than return null.
The second is that in practice, there will be fewer cases where we want a + b + c + d
with strings to return null if any of those are null, than cases where we would not.
And from that, it makes sense to treat null as an empty string in concatenations. From that basis, that (string)null + (string)null
results in ""
is because we don't have a special case for concatenating too nulls.
That special case could be added, but then the property that x + "" == x + null
would no longer hold, which could lead to some strange cases.
Thats because the Operator +=
adds the Null to Empty string.
so, the Compiler does Adding Empty String to the Existing string Object.
So it is Empty and Not null.
try this...
static void TestNullFunc(string abc)
{
if (string.IsNullOrEmpty( abc))
{
Console.WriteLine("meow THERE ! ");
}
else
{
Console.WriteLine("No Meow ");
}
}
C# borrows the behavior of its +
operator from Java. If either operand to +
is a string, the +
operator will call String.Concat
, which accepts type Object
and concatenates the results of calling ToString
on every non-null object that's passed to it. The fact that null references are simply ignored is only a small part of the way in which the operands to String.Concat
aren't regarded as "strings" per se; a much more noticeable aspect of this behavior is that types which aren't strings have their ToString
method called, whether or not they would otherwise be implicitly convertible to string
.