可空types和三元运算符:为什么? 10:null`被禁止?

我刚碰到一个奇怪的错误:

private bool GetBoolValue() { //Do some logic and return true or false } 

然后,在另一种方法,像这样的东西:

 int? x = GetBoolValue() ? 10 : null; 

很简单,如果方法返回true,则将10赋给Nullable int x。 否则,将null分配给可为空的 int。 但是,编译器抱怨:

错误1无法确定条件expression式的types,因为int<null>之间没有隐式转换。

我疯了吗?

编译器首先尝试评估右边的expression式:

 GetBoolValue() ? 10 : null 

10是一个int文字(不是int? ), nullnull 。 这两者之间没有隐含的转换,因此出现错误信息。

如果您将右侧expression式更改为下列之一,则编译是因为int?之间存在隐式转换int?null (#1)以及intint?之间int? (#2,#3)。

 GetBoolValue() ? (int?)10 : null // #1 GetBoolValue() ? 10 : (int?)null // #2 GetBoolValue() ? 10 : default(int?) // #3 

尝试这个:

 int? x = GetBoolValue() ? 10 : (int?)null; 

基本上发生的情况是条件运算符无法确定expression式的“返回types”。 因为编译器暗示决定10是一个int所以它决定这个expression式的返回types也是int 。 由于一个int不能为null (条件运算符的第三个操作数),它抱怨。

通过将null转换为Nullable<int>我们明确地告诉编译器该expression式的返回types应该是Nullable<int> 。 你可以简单地铸造10int? 也有同样的效果。

尝试这个:

int? result = condition ? 10 : default(int?);

顺便说一下,C#编译器的Microsoft实现实际上是以非常微妙和有趣的方式(以我的方式)获得对条件运算符的types分析错误。 我的文章是types推理的困境,第一部分

尝试其中之一:

 int? x = GetBoolValue() ? (int?)10 : null; int? x = GetBoolValue() ? 10 : (int?)null; 

问题是,三元运算符根据您的第一个参数赋值来推断types…在这种情况下,这是一个int,而不是一个可为空的int。

你可能有更好的运气:

 int? x = GetBoolValue() (int?)10 : null; 
 int? x = GetBoolValue() ? 10 : (int?)null; 

你看到这个的原因是因为在幕后你使用了Nullable,你需要告诉C#你的“null”是Nullable的一个空实例。

只需添加一个expression式。

 int? x = GetBoolValue() ? 10 : (int?)null; 

这是三元运算符得到混淆 – 第二个参数是一个整数,第三个参数也是一个整数,null也不适合。

这是因为编译器通过第二个和第三个操作数来确定条件操作符的types,而不是通过分配结果来确定。 编译器可以用来确定types的整型和空引用之间没有直接转换。