在C#中使用条件运算符键入结果

Vac*_*ano 11 c# nullable ternary-operator type-conversion conditional-operator

我正在尝试使用条件运算符,但我会挂起它认为结果应该是的类型.

下面是一个我设法表明我遇到的问题的例子:

class Program
{
    public static void OutputDateTime(DateTime? datetime)
    {
        Console.WriteLine(datetime);
    }

    public static bool IsDateTimeHappy(DateTime datetime)
    {
        if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0)
            return true;

        return false;
    }

    static void Main(string[] args)
    {
        DateTime myDateTime = DateTime.Now;
        OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime);
        Console.ReadLine();                        ^
    }                                              |
}                                                  |
// This line has the compile issue  ---------------+
Run Code Online (Sandbox Code Playgroud)

在上面指出的行上,我得到以下编译错误:

无法确定条件表达式的类型,因为'<null>'和'System.DateTime'之间没有隐式转换

我很困惑因为参数是可以为空的类型(DateTime?).为什么需要转换呢?如果它为null,则使用它,如果是日期时间则使用它.

我的印象是:

condition ? first_expression : second_expression;
Run Code Online (Sandbox Code Playgroud)

与以下相同:

if (condition)
   first_expression;
else
   second_expression;
Run Code Online (Sandbox Code Playgroud)

显然情况并非如此.这背后的原因是什么?

(注意:我知道,如果我将"myDateTime"设为可以为空的DateTime,那么它会起作用.但为什么需要呢?

正如我之前所说,这是一个人为的例子.在我的实例中,"myDateTime"是一个数据映射值,不能为空.)

Mar*_*ers 22

编译器不会根据结果的用法推断条件运算符的结果类型,而是根据其参数的类型.编译器在看到此表达式时失败,因为它无法推断出结果的类型:

IsDateTimeHappy(myDateTime) ? null : myDateTime;
Run Code Online (Sandbox Code Playgroud)

由于nullDateTime不兼容,您需要告诉编译器应该是什么类型.演职员应该做的伎俩:

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);
Run Code Online (Sandbox Code Playgroud)

现在编译器没有问题.如果您愿意,也可以在一行上写上面的内容(但我可能不会这样做):

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);
Run Code Online (Sandbox Code Playgroud)

Eric Lippert有一个很好的答案,这里也很重要,并详细介绍了编译器如何确定类型.