20

从 MSDN 文档中,以下两个片段是相等的:

bool value;
int x = (value) ? 0 : 1;

bool value;
int x;
if (value)
    x = 0;
else
    x = 1;

很棒,很棒。我用它所有的时间。简洁有效。

如果我们尝试使用可为空的类型,如下所示:

int? x = (value.HasValue) ? value.Value : null;

我们得到一个编译时错误:

The type of conditional expression cannot be determined
because there is no implicit conversion between '{NullableType}' and null.

这编译得很好:

int? value;
int? x;

if (value.HasValue)
    x = value.Value;
else
    x = null;

所以,我知道编译器需要(int?)null以编译第一条语句的方式进行显式转换。我不明白为什么该语句需要它,而不是If Else块。

4

5 回答 5

27

null可以表示任何基于对象的数据类型。您需要转换null为数据类型,以便它知道您在说什么。

int? x = (value.HasValue) ? value.Value : (int?)null;

我知道,这听起来有点奇怪。


要回答评论中的问题:

为什么它不是隐含的?
是的,我明白了。但是为什么我不必将它投射到 If Else 块中?

让我们看一下代码。

您的else声明如下所示:

else x = null;

这意味着您正在分配nullto的值x。这是有效的,因为x是 a int?,它需要nulls

当你有三元运算符时,区别就来了。它说:“将运算符的值分配给x”。问题(以及错误的原因)是,三元运算符的结果是什么数据类型?

从您的代码中,您无法确定,编译器会举手。

int? x = (value.HasValue) ? value.Value : null;
// int?        bool             int        ??

什么数据类型是null?您很快就会说“好吧,它是 a int?,因为另一边是 aint并且结果是 a int?”。问题是,以下情况如何:

string a = null;
bool? b = null;
SqlConnectionStringBuilder s = null;

这也是有效的,这意味着null可以用于any object-based datatype. 这就是为什么你必须明确地转换null为你想要使用的类型,因为它可以用于任何事情!


另一种解释(可能更准确):

您不能在可空值和不可空值之间进行隐式转换。

int是不可为空的(它是一个结构),在哪里null。这就是为什么在 Habib 的回答中,您可以将石膏放在左侧或右侧。

于 2013-09-12T19:06:54.500 回答
11

对于条件运算符 MSDN状态:

first_expression 和 second_expression 的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。

因此,在您的情况下,您的 first_expression 和 second_expression 是:

int? x = (value.HasValue) ? value.Value : null;
                             ^^^^^^^^      ^^^^^
                             first exp     2nd Exp

现在,如果您看到,您的第一个表达式是 type int,第二个表达式是null并且两者都不相同,并且没有隐式转换。所以将它们中的任何一个转换为`int?解决问题。

所以:

int? x = (value.HasValue) ? (int?) value.Value : null;

或者

int? x = (value.HasValue) ? value.Value : (int?) null;

没事。

现在为什么不需要它if-else,因为涉及多个语句,而不是一个分配值的语句。

于 2013-09-12T19:19:02.023 回答
6
var x = value.HasValue ? value.Value : default(int?);

也可以。

于 2013-09-12T19:07:49.837 回答
1

?: 运算符的文档说明表达式 b 的类型?x : y 通过检查 x 和 y 的类型来确定:

  • 如果 X 和 Y 是相同的类型,那么这是条件表达式的类型。
  • 否则,如果存在从 X 到 Y 的隐式转换(第 6.1 节),但不存在从 Y 到 X 的转换,则 Y 是条件表达式的类型。
  • 否则,如果存在从 Y 到 X 的隐式转换(第 6.1 节),但不存在从 X 到 Y 的隐式转换,则 X 是条件表达式的类型。
  • 否则,无法确定表达式类型,并出现编译时错误。

在你的例子中

int? x = (value.HasValue) ? value.Value : null;

int 和 null 之间没有隐式转换,因此最后一个项目符号适用。

于 2013-09-12T19:21:48.767 回答
0

原因是条件表达式的类型是由条件运算符 (?:) 的第二个和第三个运算符决定的。

由于 null 没有类型,编译器无法确定整个表达式的类型,因此会发出编译器错误。

它与简单赋值运算符 (=) 一起使用的原因是运算符的左侧决定了类型。由于在 If 语句中, x 的类型是已知的,编译器不会抱怨。

有关进一步的解释,请参见第 7.14 节(条件运算符)和第 7.17.1 节(简单赋值)。

于 2013-09-12T19:26:39.693 回答