为啥条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制]

Posted

技术标签:

【中文标题】为啥条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制]【英文标题】:Why doesn't the conditional operator correctly allow the use of "null" for assignment to nullable types? [duplicate]为什么条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制] 【发布时间】:2011-01-27 21:30:24 【问题描述】:

可能的重复:Nullable types and the ternary operator. Why won’t this work?Conditional operator assignment with nullable<value> types?

这不会编译,说明“无法确定条件表达式的类型,因为'System.DateTime'和''之间没有隐式转换”

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

这很好用

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

【问题讨论】:

你能摆脱对你的代码的依赖,这样我们就可以重现这个吗?例如,将task.ActualEndDate 替换为局部变量。 【参考方案1】:

这不起作用,因为编译器不会同时在两边插入隐式转换,而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) 。永远不要相信输入会给你一个可解析的字符串。 在此解析之前在几个地方进行验证,当我尝试将 DateTime.Min 插入数据库时​​,我更喜欢现在而不是一个异常。【参考方案2】:

条件运算符不查看返回的值。它只查看它被要求选择的值:DateTime 和 null。它无法将它们识别为相同类型的实例(因为 null 不是有效的 DateTime),因此会出现错误。你和我都知道Nullable&lt;DateTime&gt; 可以完成这项工作,但是条件运算符不允许引入“更大”的类型:它只允许查看它选择的两个表达式的类型。 (感谢 cmets 中的 Aaronaught 澄清这一点和一个很好的澄清示例。)

要解决这个问题,请通过转换 DateTime 给操作员一个提示:

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

【讨论】:

大部分正确 (+1):DateTime.Parse 返回 DateTime(不是 Nullable&lt;DateTime&gt;),它是一种值类型,与 null 之间没有任何转换。编译器在尝试解析表达式时无法将“更大”类型引入方程,它只能处理实际存在的类型。这和你不能写Stream s = expr ? new MemoryStream() : new FileStream(...)的原因是一样的。 Aaronaught:很好的解释 - 我会把它折叠起来。【参考方案3】:

原因是 null 的类型为 object,因此您必须将其转换为正确的类型,如下所示:

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

【讨论】:

【参考方案4】:

最正确的方法(IMO)是这样做

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

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

【讨论】:

【参考方案5】:

这可能是您在这种情况下遇到的错误:

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

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


修复:

您需要 cast explicitly expression ,这可能会将 null 返回到 nullable 类型。这将起作用

((DateTime?) null);

【讨论】:

【参考方案6】:

这是一个副本

Nullable types and the ternary operator: why is `? 10 : null` forbidden?

我的回答

Conditional operator cannot cast implicitly?

给出了与这个问题密切相关的分析。

我还将在 4 月份发布关于条件运算符的类似问题的博客;详情请看博客。

【讨论】:

blogs.msdn.com/ericlippert/archive/2006/05/24/… 信息量很大。谢谢。

以上是关于为啥条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C# 6.0 在使用 Null 传播运算符时不允许设置非 null 可空结构的属性?

为啥 C# 6.0 在使用 Null 传播运算符时不允许设置非 null 可空结构的属性?

为啥条件运算符是右结合的?

为啥 C 在使用条件运算符时不允许连接字符串?

为啥我无法将程序中找到的布尔结果的正确值分配给布尔变量并使用结果检查条件?

为啥在检查符号是不是存在时不能使用否定运算符?