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

Posted

技术标签:

【中文标题】? 的可空类型问题:条件运算符【英文标题】:Nullable type issue with ?: Conditional Operator 【发布时间】:2010-09-22 16:32:36 【问题描述】:

有人可以解释为什么这在 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);

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

不是我不能使用前者,而是第二种风格更符合我的其余代码。

【问题讨论】:

您可以通过使用 DateTime 为自己节省大量打字时间吗?而不是 Nullable. 【参考方案1】:

编译器告诉您它不知道如何将null 转换为DateTime

解决方法很简单:

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

请注意,Nullable&lt;DateTime&gt; 可以写成 DateTime?,这样可以节省大量输入。

【讨论】:

工作得很好,但现在你不能空检查 foo - 它总是有一个值。但是没有办法解决这个问题 - 正如 MojoFilter 所说“这是因为在三元运算符中,两个值必须是相同的类型。” @DilbertDave MojoFilter 的帖子信息不正确。 我要补充一点,编译器试图猜测三元运算的结果类型不是通过查看分配给它的变量,而是查看操作数。它找到&lt;null&gt;DateTime,而不是找到共同的祖先类型,它只是试图找到彼此之间的转换。 (额外的一点:C# 识别 &lt;null&gt; 类型,即每个 null 表达式的类型。) 如果它已经被问了很多次,重复的问题标志在哪里? @starmandeluxe 他们都可能指向这里(至少我是如何到达这里的)【参考方案2】:

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

【讨论】:

不,它们不必是同一类型。第二个操作数必须可以隐式转换为第三个操作数的类型,或者反过来。【参考方案3】:

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

??

这样使用:

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

【讨论】:

这如何回答他的问题?? 如果某些条件为真,Nick 会尝试将 null 分配给 foo。如果 foo 为空,则空合并将 DateTime(0) 分配给值。两者完全无关。 因此仅供参考,离题但很高兴知道。 啊,好的。知道这一点非常有用。【参考方案4】:

另一个类似于接受的解决方案是使用 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);

【讨论】:

不正确,default(DateTime)不为空,是“1.1.0001 0:00:00”,和new DateTime(0)一样。 @IllidanS4,我没有说它等于null,只是通过使用default(),您可以将它分配给nullable 值(如MSDN 所述)。我展示的示例展示了它可以与Nullable&lt;DateTime&gt;DateTime? 和简单的DateTime 一起使用的多功能性。如果您认为这是不正确的,您能否提供这些失败的 PoC? 好吧,提问者想在变量中存储null,而不是default(DateTime),所以这充其量是误导。这不是您暗示的“通用”,因为整个表达式仍然具有相同的类型 - DateTime,您可以将 default(DateTime) 替换为 new DateTime(),它会做同样的事情。也许default(DateTime?) 是您的意思,因为它实际上等于null【参考方案5】:

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

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

第二个是让DateTime与null兼容(例如,将DateTime转换为DateTime?)。

【讨论】:

以上是关于? 的可空类型问题:条件运算符的主要内容,如果未能解决你的问题,请参考以下文章

C# 的可空合并运算符(??)到底是怎样的宝宝?

可空类型和三元运算符:为啥是`? 10:null`禁止? [复制]

可空类型 int?及?相关运算符

c# ?和?? 用法

VS 2012 中的条件运算符类型转换

在可空类型上使用合并空运算符会更改隐式类型