Почему следующий условный оператор "?:" Компилируется, но выдает ошибку во время выполнения

Я не могу понять, почему следующая программа компилируется без предупреждений, но в блоке исключений условный оператор дает исключение 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));
            }
        }
    }
}

Я знаю о ?? оператор, мой вопрос о том, почему первая строка в обработчике исключений дает исключение NullReferenceException.

2 ответа

Решение
ex.Message + ex.InnerException

превращается в

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

он проверяет свои аргументы на нулевое значение и преобразует их в строки только в том случае, если это не так. Это означает, что

ex.Message + ex.InnerException == null

является false так что выражение

Environment.NewLine + ex.InnerException.Message

оценивается. Это создает исключение, так как ex.InnerException нулевой.

Если InnerException является нулевым, но ex.Message нет, тогда первое выражение будет равнозначно false и будет пытаться получить доступ ex.InnerException.Message который дает вам NullReferenceException,

Во втором выражении вы пытаетесь получить доступ ex.InnerException.Message только если ex.InnerException не является нулевым, и именно поэтому он работает..

NullReferenceException происходит, когда вы пытаетесь получить доступ к элементу (методу, свойству, полю и т. д.) с нулевым значением object. В вашем первом примере:

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

вы соединяете новую строку с message2 и вы не получаете доступ к каким-либо свойствам или методам на message2 Это просто добавляет пустую строку для нулевых значений. Посмотрите документацию string.Concat:

Метод объединяет str0 и str1; он не добавляет разделителей. Пустая строка используется вместо любого нулевого аргумента.

Если вы напишите:

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

Тогда вы получите исключение.

Другие вопросы по тегам