3

我正在使用一个可为空的 DateTime 对象并遇到了一些奇怪的行为。这是一个示例函数:

    public DateTime? Weird()
    {
        DateTime check = DateTime.Now;
        DateTime? dt;
        if (check == DateTime.MinValue)
            dt = null;
        else
            dt = Viewer.ActiveThroughUTC.ToLocalTime();

        //this line give a compile error
        dt = (check == DateTime.MinValue) ? (null) : (Viewer.ActiveThroughUTC.ToLocalTime());
        return dt;
    }

据我所知,三元运算符的行应该与前面四行相同,但是VS2010给我一个编译错误,说<null>和DateTime之间不存在转换(即使有问题的对象是'DateTime ?')。关于三元运算符,我应该知道些什么,或者这(喘气?)是一个错误?

4

5 回答 5

10

?:运算符中的两个元素应该是相同的类型(但不必是 - 请参阅下面的详细信息)。投射nullDateTime?

dt = (check == DateTime.MinValue) ? (DateTime?)null : ...

规格

?: 运算符的第二个和第三个操作数控制条件表达式的类型。设 X 和 Y 是第二个和第三个操作数的类型。然后,

如果 X 和 Y 是相同的类型,那么这是条件表达式的类型。

  • 否则,如果存在从 X 到 Y 的隐式转换(第 6.1 节),但不存在从 Y 到 X 的转换,则 Y 是条件表达式的类型。
  • 否则,如果存在从 Y 到 X 的隐式转换(第 6.1 节),但不存在从 X 到 Y 的隐式转换,则 X 是条件表达式的类型。
  • 否则,无法确定表达式类型,并出现编译时错误。

(有趣的是,它实际上并没有被称为“三元”运算符。它是一种可能的三元(三值)运算符,我不知道 C# 中有任何其他运算符。它被称为“?:”运算符,这有点难发音。也称为“条件”运算符。)

于 2010-10-07T00:02:57.383 回答
3

几个答案错误地指出条件运算符的两个值必须是相同的类型。这绝对是不真实的,在语言规范的第 7.13 节中有详细介绍

来自规范(X 和 Y 是两个值的类型)

  • 如果 X 和 Y 是相同的类型,那么这是条件表达式的类型。
  • 否则,如果存在从 X 到 Y 的隐式转换(第 6.1 节),而不是从 Y 到 X,则 Y 是条件表达式的类型。
  • 否则,如果存在从 Y 到 X 的隐式转换(第 6.1 节),而不是从 X 到 Y,则 X 是条件表达式的类型。
  • 否则,无法确定表达式类型,并出现编译时错误。

第二种和第三种情况允许类型不同,只要存在从一种到另一种的隐式转换(但不返回)。

解决这种情况的最简单方法是将其中一个操作数显式转换为DateTime?

DateTime? dt = (check == DateTime.MinValue) 
  ? (DateTime?)null
  : Viewer.ActiveThroughUTC.ToLocalTime();
于 2010-10-07T00:12:20.760 回答
0

使用三元运算符,参数必须是相同的类型。将其更改为:

dt = (check == DateTime.MinValue) ? (DateTime?)null : 
        (DateTime?)Viewer.ActiveThroughUTC.ToLocalTime();   

对第二个参数(真正的日期时间)的强制转换可能不是必需的,因为从 fropmDateTime到有一个隐式强制转换DateTime?,并且第一个强制转换(DateTime?)null告诉编译器将其强制转换为什么......

于 2010-10-07T00:05:34.670 回答
0

使用新的 DateTime?() 插入 null。这样它就知道表达式应该是什么类型。

dt = check == DateTime.MinValue ? new DateTime?() : DateTime.Now;
于 2010-10-07T00:08:00.973 回答
0

条件语句的返回选项必须是相同的类型(或者只有一个最可以隐式转换),隐式转换为编译器推断的可空值:

dt = null;

在这里不会发生(如果它们不同,应该将第一个转换为第二个?反之亦然?),因此每个选项的返回类型需要匹配或可转换。例如,这将起作用:

dt = check == DateTime.MinValue ? (DateTime?)null : Viewer.ActiveThroughUTC.ToLocalTime();
于 2010-10-07T00:04:12.210 回答