条件运算符 ?:使用可为空的类型转换
本文关键字:类型转换 条件运算符 | 更新日期: 2023-09-27 18:31:03
根据 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
块。
null
可以表示任何基于对象的数据类型。您需要将null
转换为数据类型,以便它知道您在说什么。
int? x = (value.HasValue) ? value.Value : (int?)null;
我知道,这听起来有点奇怪。
要回答评论中的问题:
为什么它不是隐含的?
是的,我明白了。但是为什么我不必在 If Else 块中投射它呢?
让我们演练一下代码。
您的else
语句如下所示:
else x = null;
这意味着您将 null
的值分配给 x
。这是有效的,因为x
是一个int?
,需要nulls
。
当你有三元运算符时,区别就来了。它说:"将运算符的值分配给x
"。问题(以及错误的原因)是,三元运算符的结果是什么数据类型?
从你的代码中,你无法确定,编译器举起了手。
int? x = (value.HasValue) ? value.Value : null;
// int? bool int ??
null
什么数据类型?你很快就会说"嗯,这是一个int?
,因为另一边是一个int
,结果是一个int?
"。问题是,以下情况如何:
string a = null;
bool? b = null;
SqlConnectionStringBuilder s = null;
这也是有效的,这意味着null
可用于any object-based datatype
。这就是为什么您必须显式地将null
转换为要使用的类型,因为它可以用于任何用途!
另一种解释(可能更准确):
不能在可为空值和不可为空的值之间进行隐式强制转换。
int
不可为空(它是一个结构),其中null
是。这就是为什么在哈比卜的回答中,你可以把演员放在左边或右边。
对于条件运算符 MSDN 声明:
first_expression和second_expression的类型必须是 相同,或者必须存在从一种类型到 另一个。
因此,在您的情况下,您的first_expression和second_expression是:
int? x = (value.HasValue) ? value.Value : null;
^^^^^^^^ ^^^^^
first exp 2nd Exp
现在,如果您看到,您的第一个表达式是 int
类型,第二个表达式是 null
并且两者不相同,并且没有隐式转换。所以把他们中的任何一个投到'int?解决了问题。
所以:
int? x = (value.HasValue) ? (int?) value.Value : null;
或
int? x = (value.HasValue) ? value.Value : (int?) null;
都很好。
现在为什么不需要if-else
,因为涉及多个语句,而不是分配值的单个语句。
var x = value.HasValue ? value.Value : default(int?);
也有效。
运算符的文档指出表达式 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 之间没有隐式转换,因此最后一个项目符号适用。
原因是条件表达式的类型由条件运算符 (?:) 的第二个和第三个运算符确定。
由于 null 没有类型,因此编译器无法确定整体表达式的类型,因此会发出编译器错误。
它与简单赋值运算符 (=) 一起使用的原因是运算符的左侧决定了类型。 由于在 If 语句中,x 的类型是已知的,因此编译器不会抱怨。
有关进一步说明,请参阅第 7.14 节(条件运算符)和第 7.17.1 节(简单赋值)。