?的可空类型问题:条件运算符


154

有人可以解释为什么这在C#.NET 2.0中有效:

    Nullable<DateTime> foo;
    if (true)
        foo = null;
    else
        foo = new DateTime(0);

...但这不是:

    Nullable<DateTime> foo;
    foo = true ? null : new DateTime(0);

后一种形式给我带来了一个编译错误“无法确定条件表达式的类型,因为'<null>'和'System.DateTime'之间没有隐式转换。”

不是说我不能使用前一种样式,而是第二种样式与我的其余代码更加一致。


12
您可以使用DateTime节省很多输入时间?而不是Nullable <DateTime>。
斯图尔特·约翰逊

Answers:


325

这个问题已经被问过很多遍了。编译器告诉您,它不知道如何转换nullDateTime

解决方案很简单:

DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);

请注意,Nullable<DateTime>可以编写代码DateTime?,这样可以节省大量打字时间。


效果很好,但是现在您不能对foo空检查-它将始终具有一个值。但是没有办法解决-正如MojoFilter所说:“这是因为在三元运算符中,两个值必须是相同的类型。”
DilbertDave 2012年

@DilbertDave MojoFilter的帖子中的信息不正确。
Mishax 2013年

4
我要补充一点,编译器不是通过查看分配给它的变量而是通过查看操作数来猜测三元运算的结果类型。它查找<null>并且DateTime不查找公共祖先类型,而只是尝试查找彼此之间的转换。(额外的位:C#可以识别<null>类型,即每个null表达式的类型。)
IllidanS4希望Monica返回

如果已经被问过很多遍,那么重复的问题标记在哪里?
starmandeluxe

@starmandeluxe他们都可能指向这里(至少我是怎么到达这里的)
Scott Chamberlain

19

仅供参考(离题,但很漂亮,并且与可空类型有关),我们有一个方便的运算符,用于可空类型,称为空合并运算符

??

像这样使用:

// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);

9
这如何回答他的问题?
斯图尔特·约翰逊

3
如果某些条件为真,尼克将尝试为foo分配null。如果foo为空,则空合并将为DateTime(0)分配值。两者是完全无关的。
Jeromy Irvine

4
因此,仅供参考,但很高兴知道。
FlySwat

喔好吧。知道这很有用。
Jeromy Irvine,

8

这是因为在三元运算符中,两个值必须解析为相同的类型。


10
不,他们不必是同一类型。第二个操作数必须隐式转换为第三个操作数的类型,或者相反。
Mishax 2013年

3

我知道这个问题是在2008年提出的,现在已经过了5年,但是标记为答案的答案并不令我满意。真正的答案是DateTime是一个结构,并且作为结构它与null不兼容。您有两种解决方法:

首先是使null与DateTime兼容(例如,按70票赞成的绅士建议,将null转换为DateTime ?,或将null转换为Object或ValueType)。

第二个方法是使DateTime与null兼容(例如,将DateTime强制转换为DateTime?)。


3

类似于接受的另一种解决方案是使用C#的default关键字。使用泛型定义时,它实际上适用于任何类型。

适用于OP的问题的示例用法:

Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);

当前接受的答案的用法示例:

DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);

另外,通过使用default,您无需指定变量nullable即可为其分配null值。编译器将自动分配特定变量类型的默认值,并且不会遇到错误。例:

DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);

13
不正确,default(DateTime)不为null 1.1.0001 0:00:00,与相同new DateTime(0)
IllidanS4希望莫妮卡回到2014年

@ IllidanS4,我不是说它等于null,只是说通过使用default()它可以将其分配给一个nullable值(如MSDN所述)。我的例子显示表明,它可以与使用的多功能性Nullable<DateTime>DateTime?以及简单DateTime。如果您认为这是不正确的,那么您可以在这些操作失败的地方提供PoC吗?
newfurniturey

3
好吧,发问者想将其存储null在变量中,而不是default(DateTime),因此这充其量是一种误导。正如您所暗示的那样,这并不是“通用”的,因为整个表达式仍然具有相同的类型- DateTime,并且您可以替换default(DateTime)new DateTime()并且它将执行相同的操作。也许default(DateTime?)就是您的意思,因为它实际上等于null
IllidanS4希望莫妮卡回到
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.