Почему следующий условный оператор "?:" Компилируется, но выдает ошибку во время выполнения
Я не могу понять, почему следующая программа компилируется без предупреждений, но в блоке исключений условный оператор дает исключение 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();
Тогда вы получите исключение.