为什么条件运算符不能正确地允许将“null”用于可空类型的赋值?

8
这段代码无法编译,提示“条件表达式的类型无法确定,因为'System.DateTime'和''之间没有隐式转换”。
可能的重复问题:
可空类型和三元运算符。为什么不起作用?
带有可空<value>类型的条件运算符赋值?
task.ActualEndDate = TextBoxActualEndDate.Text != "" ? DateTime.Parse(TextBoxActualEndDate.Text) : null;

这个很好地工作

 if (TextBoxActualEndDate.Text != "")
    task.ActualEndDate = DateTime.Parse(TextBoxActualEndDate.Text);
else
    task.ActualEndDate = null;

2
你能否消除代码中的依赖关系,以便我们可以重现这个问题?例如,用一个本地变量替换 task.ActualEndDate - Jay Bazuzi
6个回答

8

这段代码不起作用是因为编译器不会同时在两侧插入隐式转换,而 null 需要进行隐式转换才能成为可空类型。

相反,您可以编写

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    DateTime.Parse(TextBoxActualEndDate.Text) : new DateTime?();

这只需要一个隐式转换 (DateTimeDateTime?)。

或者,您可以将任一侧强制转换:

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    (DateTime?)DateTime.Parse(TextBoxActualEndDate.Text) : null;

这也只需要一次隐式转换。

你真的应该在那里使用 DateTime.TryParse(TextBoxActualEndDate.Text, out someDateVar)。永远不要相信输入会给你一个可解析的字符串。 - Tomas
2
在此解析之前,会有几个地方进行验证,我宁愿现在抛出异常,也不想在尝试将DateTime.Min插入数据库时再抛出异常。 - Daniel Coffman

4
条件运算符并不关注返回值的类型,而只关注其选择的值:DateTime和null。它无法将它们识别为同一类型的实例(因为null不是有效的DateTime),因此会出现错误。我们知道Nullable<DateTime>可以完成这项工作,但条件运算符不允许引入“更大”的类型:它只能查看它正在选择的两个表达式的类型。(感谢Aaronaught在评论中对这一点进行澄清,并提供了一个很好的澄清示例。)
要解决这个问题,请通过对DateTime进行转换来给操作员一个提示:
TextBoxActualEndDate.Text != "" ? (DateTime?)(DateTime.Parse(TextBoxActualEndDate.Text)) : null;
                                  ^^^^^^^^^^^

2
大多数情况下正确 (+1):DateTime.Parse 返回一个 DateTime(而不是 Nullable<DateTime>),它是一个值类型,没有与 null 的转换。编译器在尝试解析表达式时无法引入“更大”的类型,它只能使用实际存在的类型。这就是为什么您不能编写 Stream s = expr ? new MemoryStream() : new FileStream(...) 的原因。 - Aaronaught
Aaronaught:非常好的解释 - 我会采纳的。 - itowlson

1

1
http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woes-part-one.aspx非常有启发性。谢谢。 - Daniel Coffman

0
原因是null是object类型,所以你必须将其转换为正确的类型,就像这样:
task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    DateTime.Parse(TextBoxActualEndDate.Text) : ((DateTime?) null);

0

在我看来,最正确的方法是这样做

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    (DateTime?)(DateTime.Parse(TextBoxActualEndDate.Text) : null);

我经常使用空值合并运算符以这种方式。


0

在这种情况下,您可能会遇到以下错误:

error CS0173: 无法确定条件表达式的类型,因为''和'int'之间没有隐式转换

编译器解释说它不知道如何将null转换为DateTime


修复:

您需要将可能返回 nullexpression 强制转换为 nullable 类型。这样就能正常工作。

((DateTime?) null);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接