条件运算符?:具有Nullable类型的Casting

时间:2013-09-12 19:04:01

标签: c# .net

从MSDN文档中,以下两个代码段是相同的:

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

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

太好了,很精彩。我用它所有的时间。 Terse and effective。

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

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块。

5 个答案:

答案 0 :(得分:26)

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

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

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


回答评论中的问题:

  

为什么不隐含呢?   是的,我明白了。但为什么我不必把它放在If Else块中?

让我们来看看代码。

您的else语句如下所示:

else x = null;

这意味着您要将null的值分配给x。这是有效的,因为xint?,需要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是。{1}}。这就是为什么在Habib的回答中你可以把演员放在左侧或右侧。

答案 1 :(得分:11)

对于Condtional operator 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不需要它,因为涉及多个语句,而不是分配值的单个语句。

答案 2 :(得分:6)

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

也有效。

答案 3 :(得分:1)

documentation for the ?: operator表示表达式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之间没有隐式转换,因此适用最后一个项目符号。

答案 4 :(得分:0)

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

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

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

有关进一步说明,请参阅第7.14节(条件运算符)和第7.17.1节(简单赋值)。