42

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).

asteri
  • 11,402
  • 13
  • 60
  • 84
spetzz
  • 679
  • 8
  • 19
  • 1
    Try using string.IsNullOrEmpty(string s) :) – qstebom Feb 14 '14 at 11:42
  • You can't join two strings if they're not there. – BoltClock Feb 14 '14 at 11:42
  • 2
    @qstebom: You may as well tell him to change the nulls into empty strings then. – BoltClock Feb 14 '14 at 11:43
  • 2
    @BoltClock: Depends on what he really wants to achieve. In this case, he probably just wonders why his code doesn't result in NullReferenceException. – qstebom Feb 14 '14 at 11:49
  • Loving lol meow as not null indicator:-D – Srb1313711 Feb 14 '14 at 13:51
  • It is for the same reason that `string n = null; Console.WriteLine(n + n == "");` writes out "True". When you concatenate strings with the `+` operator, the result is never null. – Jeppe Stig Nielsen Feb 14 '14 at 15:10
  • 10
    Fun fact: My first task working on the C# compiler was to rewrite the optimizer for string concatenations. How would you optimize `M() + null` where `M()` returns a string? Rather than generating `String.Concat(M(), null)` or `String.Concat(M(), "")` the compiler generates the equivalent of `M() ?? ""`. That is, use `M()`, but if it returns `null` then use `""`. – Eric Lippert Feb 14 '14 at 18:00

6 Answers6

67

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.

dcastro
  • 66,540
  • 21
  • 145
  • 155
24

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
Alberto
  • 15,626
  • 9
  • 43
  • 56
  • 4
    Picky point: actually the compiler will elide calls to `String.Concat` in the rare cases that it can get away with it. – Eric Lippert Feb 14 '14 at 18:07
6

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:

  1. The result is null.
  2. 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.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
2

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.

Gokul E
  • 1,356
  • 2
  • 13
  • 28
2

try this...

static void TestNullFunc(string abc)
{
    if (string.IsNullOrEmpty( abc))
    {
        Console.WriteLine("meow THERE ! ");
    }
    else
    {
        Console.WriteLine("No Meow ");
    }
}
Amit Tiwari
  • 368
  • 1
  • 4
  • Nothing wrong with this solution, but I will point out that it uses more memory than the other solutions posted on here (the `string.IsNullOrEmpty( abc))`. – AStopher Feb 14 '14 at 12:14
  • 4
    How will it use more memory, `IsNullOrEmpty(abc)` is just a shortcut for `abc == null || abc.Length == 0` and small enough to be in-lined by jitter – Tseng Feb 14 '14 at 12:41
  • Any `string` function uses more memory, according to a C# programmer friend. Is this statement wrong/invalid? – AStopher Feb 14 '14 at 12:58
  • 4
    @zyboxenterprises yes, it is wrong. There's no extra memory allocation involved, whatsoever, when calling `IsNullOrEmpty`. As Tseng said, the method will probably be inlined, so there won't even be a difference in performance either. Your friend might mean that, in rare circumstances (e.g., performance critical applications), you *could* do better than using *some* string methods, such as parsing a string in-place instead of using stuff like `Split`. See [Joe Duffy - Beware the string](http://joeduffyblog.com/2012/10/30/beware-the-string/) – dcastro Feb 14 '14 at 13:28
  • @zyboxenterprises But even that is debatable (see evildictaitor's post [here](http://channel9.msdn.com/Forums/Coffeehouse/Joe-Duffy--a-managed-system--beat-the-pants-off-all-the-popular-native-programming-environments/d78ab9e23cf741ca9f1ca10f010b4121)). – dcastro Feb 14 '14 at 16:05
1

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.

Graham Clark
  • 12,886
  • 8
  • 50
  • 82
supercat
  • 77,689
  • 9
  • 166
  • 211