11

我正在尝试使用条件运算符,但我对它认为结果应该是的类型感到困惑。

以下是我试图展示我遇到的问题的示例:

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  ---------------+

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

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

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

我的印象是:

condition ? first_expression : second_expression;

与以下内容相同:

if (condition)
   first_expression;
else
   second_expression;

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

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

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

4

5 回答 5

22

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

IsDateTimeHappy(myDateTime) ? null : myDateTime;

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

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);

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

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);

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

于 2010-05-11T23:06:26.250 回答
2

原因是三元运算符希望两个操作数属于同一类型。整个运算符在分配给结果(在这种情况下传递给函数)之前得到解决,因此编译器无法知道结果类型是什么。

IsDateTimeHappy(myDateTime) ? null : myDateTime

null在上述情况下,和之间没有转换路径DateTime。只要将其中一个转换为DateTime?,编译器就可以转换另一个:

IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime

上面的第一行代码有效,因为编译器可以通过隐式转换运算符转换DateTime为:DateTime?

//In Nullable<T>
public static implicit operator T?(T value);

第二行有效,因为null可以分配给,DateTime?因为后者是引用类型。

于 2010-05-11T23:08:17.013 回答
1

return 语句不允许隐式转换。如果你有

if (condition)
    return first_expression;
else
    return second_expression;

然后你会比较苹果和苹果。而且你没有问题 - 正如你所说。

在您的情况下,您在堆栈上为 DateTime 分配了这么多空间 - 这是一种不可为空的值类型。所以你正在做一个对编译器没有任何意义的声明。如果你说,我要传给你 anA或 a B,那么 theAB需要是同一件事。在您的情况下, theB永远不能是A.

于 2010-05-11T23:04:10.583 回答
0

编译器的意思是:

如果IsDateTimeHappy(myDateTime)false,那么我需要返回一个类型DateTime等于的值myDateTime。如果是true,那么我需要返回一个等于 的值null,但是你没有告诉我它应该是什么类型!

这就是为什么马克的答案是解决方案。在你提供一个转换告诉编译器如果条件是 将返回什么类型的值之后true,它可以检查truefalse返回值是否可以转换为(或属于)相同的类型。

干杯马克!;-)

于 2010-05-11T23:08:27.587 回答
0

而不是null使用default(DateTime?)然后三元的两侧将具有兼容的类型。

于 2010-05-11T23:12:40.953 回答