0

I cannot figure out why the following program compiles without warnings, but in the exception block the conditional operator gives a NullReferenceException.

using System;

namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            string message1 = "First message.";
            string message2 = null;
            // This works without a problem
            Console.WriteLine(message1 + message2 == null ? "" : Environment.NewLine + message2);
            Console.ReadKey();

            try
            {
                throw new Exception("Now with an exception.");
            }
            catch (Exception ex)
            {
                // This will give a NullReferenceException:
                Console.WriteLine(ex.Message + ex.InnerException == null ? "" : Environment.NewLine + ex.InnerException.Message);
                // ..But this will work:
                Console.WriteLine(ex.Message + (ex.InnerException == null ? "" : Environment.NewLine + ex.InnerException.Message));
            }
        }
    }
}

I know about the ?? operator, my question is about why the first line in the exception handler gives a NullReferenceException.

Meine
  • 53
  • 8
  • @Atomosk *(Environment.NewLine + ex.InnerException.Message) should do the trick* If `ex.InnerException` is null, then the exception will still be thrown – sloth Jul 01 '14 at 08:09
  • The "But this will work:" line is massively different to the other line, I do hope you realise that. Besides `ex.Message + ex.InnerException == null` as your condition doesn't really make any sense. Here it is false when the innerException is null because "foo" + null = "foo" – Nathan Cooper Jul 01 '14 at 08:10
  • Without parentheses it's equivalent to 'concatenate ex.Message with ex.InnerException.ToString(), then compare result with null'. – Atomosk Jul 01 '14 at 08:16
  • So why does `Console.WriteLine(message1 + message2 == null ? "" : Environment.NewLine + message2);` work? – Meine Jul 01 '14 at 08:17
  • @Meine Concatenation with null is ok, calling `Message` of null is exception. Change `Environment.NewLine + message2` to `Environment.NewLine + message2.ToString()` and it will throw exception. – Atomosk Jul 01 '14 at 08:27

2 Answers2

4
ex.Message + ex.InnerException

is converted into

string.Concat(ex.Message, ex.InnerException);

this checks its arguments for null and only converts them to strings if they are not. This means that

ex.Message + ex.InnerException == null

is false so the expression

Environment.NewLine + ex.InnerException.Message

is evaluated. This throws an exception since ex.InnerException is null.

Lee
  • 142,018
  • 20
  • 234
  • 287
  • _only converts them to strings if they are not._ no it doesn't. it adds an empty string for null values. – Selman Genç Jul 01 '14 at 08:15
  • @Selman22 - Right, I mean it doesn't call `ToString` on them. `string.Empty` is the identity for string concatenation so there's no visible difference between doing nothing and concatenating `string.Empty`. – Lee Jul 01 '14 at 08:17
  • So why does `Console.WriteLine(message1 + message2 == null ? "" : Environment.NewLine + message2);` work? – Meine Jul 01 '14 at 08:18
  • @Meine because you are not trying to access any member of message2, even if it's null it just returns an empty string. – Selman Genç Jul 01 '14 at 08:20
  • @Meine - The code in your question throws because you are trying to access the `Message` property of a `null` object. `string.Concat` is safe for null arguments, so `message1 + message2` is safe if `message1` or `message2` are null. If you tried to evaluate `message1.Length` in the else branch you would also get an exception. – Lee Jul 01 '14 at 08:22
1

if InnerException is null but ex.Message isn't, then the first expression will evalute to false and will try to access ex.InnerException.Message which is giving you the NullReferenceException.

In the second expression you are trying to access ex.InnerException.Message only if the ex.InnerException is not null and that's why it works..

NullReferenceException occurs when you are trying to access a member (method, property, field etc.) of a null object.In your first example:

message1 + message2 == null ? "" : Environment.NewLine + message2;

you are concatenating the new line with message2 and you are not accessing any properties or methods on message2.It just adds an empty string for null values.Take a look at the documentation of string.Concat:

The method concatenates str0 and str1; it does not add any delimiters. An Empty string is used in place of any null argument.

If you write:

message1 + message2 == null ? "" : Environment.NewLine + message2.ToString();

Then you will get an exception.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • I like this answer very much because it also addresses why the strings example does not throw an error. But @Lee's example addresses my question in a very clear manner, so I've marked his answer as the answer. – Meine Jul 01 '14 at 11:57