为啥条件运算符不能正确地允许使用“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?();
这只需要一次隐式转换(DateTime
到 DateTime?
)。
或者,您可以投射左侧:
task.ActualEndDate = TextBoxActualEndDate.Text != "" ?
(DateTime?)DateTime.Parse(TextBoxActualEndDate.Text) : null;
这也只需要一次隐式转换。
【讨论】:
你真的应该在那里使用 DateTime.TryParse(TextBoxActualEndDate.Text, out someDateVar) 。永远不要相信输入会给你一个可解析的字符串。 在此解析之前在几个地方进行验证,当我尝试将 DateTime.Min 插入数据库时,我更喜欢现在而不是一个异常。【参考方案2】:条件运算符不查看返回的值。它只查看它被要求选择的值:DateTime 和 null。它无法将它们识别为相同类型的实例(因为 null 不是有效的 DateTime),因此会出现错误。你和我都知道Nullable<DateTime>
可以完成这项工作,但是条件运算符不允许引入“更大”的类型:它只允许查看它选择的两个表达式的类型。 (感谢 cmets 中的 Aaronaught 澄清这一点和一个很好的澄清示例。)
要解决这个问题,请通过转换 DateTime 给操作员一个提示:
TextBoxActualEndDate.Text != "" ? (DateTime?)(DateTime.Parse(TextBoxActualEndDate.Text)) : null;
^^^^^^^^^^^
【讨论】:
大部分正确 (+1):DateTime.Parse
返回 DateTime
(不是 Nullable<DateTime>
),它是一种值类型,与 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 可空结构的属性?