关于c#:Nullable类型和三元运算符:为什么是`?

Nullable types and the ternary operator: why is `? 10 : null` forbidden?

本问题已经有最佳答案,请猛点这里访问。

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

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

然后,在另一种方法中,像这样:

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

简单,如果方法返回true,则将10赋给nullablintx。否则,将null赋给nullable int。但是,编译器会抱怨:

Error 1 Type of conditional expression cannot be determined because there is no implicit conversion between int and .

我疯了吗?


编译器首先尝试计算右侧表达式:

1
GetBoolValue() ? 10 : null

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

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

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


试试这个:

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

基本上,所发生的是条件运算符无法确定表达式的"返回类型"。由于编译器隐含地决定10int,因此它决定这个表达式的返回类型也应该是int。由于int不能是null(条件运算符的第三个操作数),它会抱怨。

通过将null强制转换为Nullable,我们明确地告诉编译器这个表达式的返回类型应该是Nullable。你也可以很容易地把10铸造成int?,效果也一样。


试试这个:

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


顺便说一句,C编译器的微软实现实际上以一种非常微妙和有趣的方式(对我来说)使条件运算符的类型分析出错。我的文章是关于类型推理的悲哀,第一部分。


问题是三元运算符是根据第一个参数赋值推断类型的…在本例中是int,而不是可为空的int。

你可能更幸运的是:

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

尝试以下方法之一:

1
2
3
int? x = GetBoolValue() ? (int?)10 : null;

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


这是因为编译器通过第二个和第三个操作数来确定条件运算符的类型,而不是通过将结果赋给什么。整数和空引用之间没有直接强制转换,编译器可以使用它来确定类型。


只需添加一个解释演员。

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

三元运算符混淆了,第二个参数是整数,第三个参数也被检查为整数,而NULL不适合。


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

您看到这一点的原因是,在您使用nullable的幕后,您需要告诉C您的"nullable"是nullable的一个空实例。