C#中的三元运算符和if语句之间是否存在差异?

时间:2010-10-07 00:00:14

标签: c# ternary-operator

我正在使用可以为空的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?')。有什么我应该知道的关于三元运算符的东西还是这个(喘气?)一个错误?

5 个答案:

答案 0 :(得分:10)

?:运算符中的两个元素应属于同一类型(但不一定是 - 请参阅下面的详细信息)。将null投射到DateTime?

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

来自spec

  

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

     

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

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

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

答案 1 :(得分: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();

答案 2 :(得分:0)

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

dt = null;

这里不会发生(如果第一次被转换为第二次会有所不同吗?反之亦然?),所以每个选项的返回类型需要才能匹配或转换。例如,这将起作用:

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

答案 3 :(得分:0)

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

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

第二个参数(实际日期)上的强制转换可能没有必要,因为有一个隐式的转换fropm DateTimeDateTime?,并且第一个转换(DateTime?)null告诉编译器什么把它投到......

答案 4 :(得分:0)

使用新的日期时间?()而不是null。这样它就知道表达式应该是什么类型。

dt = check == DateTime.MinValue ? new DateTime?() : DateTime.Now;