为什么以下条件运算符"?:"编译,但给出运行时错误

时间:2014-07-01 08:04:53

标签: c# conditional-expressions

我无法弄清楚为什么以下程序在没有警告的情况下编译,但在异常块中,条件运算符给出了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 个答案:

答案 0 :(得分:4)

ex.Message + ex.InnerException

转换为

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

这会将其参数检查为null,并且只有在它们不是时才将它们转换为字符串。 这意味着

ex.Message + ex.InnerException == null

false所以表达式

Environment.NewLine + ex.InnerException.Message
评估

。由于ex.InnerException为空,因此抛出异常。

答案 1 :(得分:1)

如果InnerException为空,但ex.Message不是,那么第一个表达式将评估为false并尝试访问ex.InnerException.Message,它将为您提供NullReferenceException

在第二个表达式中,如果ex.InnerException.Message ,则您只会尝试访问ex.InnerException ,这就是为什么它工程..

当您尝试访问null NullReferenceException的成员(方法,属性,字段等)时,会出现

object。在您的第一个示例中:

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

您正在使用message2连接新行,并且您没有访问message2上的任何属性或方法。它只是为空值添加一个空字符串。请查看{{3} } string.Concat

  

该方法连接str0和str1;它不会添加任何分隔符。      使用空字符串代替任何空参数。

如果你写:

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

然后你会得到一个例外。

相关问题