以下代码无法编译:
//int a = ...
int? b = (int?) (a != 0 ? a : null);
为了编译,需要将其更改为
int? b = (a != 0 ? a : (int?) null);
由于b = null
和b = a
都是合法的,这对我来说没有意义。
为什么我们必须将null
强制转换为int?
?为什么我们不能简单地为整个表达式提供一个显式的类型转换(我知道在其他情况下是可能的)? / p>
答案 0 :(得分:18)
从C#语言规范的第7.13章开始:
?:运算符的第二个和第三个操作数控制条件表达式的类型。设X和Y是第二个和第三个操作数的类型。然后,
- 如果X和Y是相同的类型,则这是条件表达式的类型。
- 否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型。
- 否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型。
- 否则,无法确定表达式类型,并发生编译时错误。
在您的情况下,没有从int到null的隐式转换,反之亦然。你的演员解决了这个问题,int可以转换为int?
答案 1 :(得分:5)
?:
运算符的两个备选方案必须属于同一类型。
否则,编译器无法推断出整个条件表达式的类型。
null
不是int
,因此您需要向编译器提示结果类型为int?
。
编辑:正如其他人指出的那样,这两种类型不需要相同,但其中一种应该可以转换为另一种(另一种将是结果类型)。有关详细信息,请参阅specs。
答案 2 :(得分:5)
如果您使用default(int?)
代替null
,则可以避免投射。
int a = 42;
int? b = (a != 0 ? a : default(int?));
答案 3 :(得分:1)
这是因为当你使用那种表示法时,两个成员必须属于同一类型,所以你必须明确说“这个成员是一个int?”。
很清楚吗?
答案 4 :(得分:1)
当您使用具有不同类型操作数的条件运算符时,编译器将检查其中一种类型是否可以隐式转换为另一种类型。
如果两种类型都不能隐式转换为另一种类型,它将产生错误,即使存在可以隐式转换为的第三种类型。编译器不会立即在两端插入隐式转换。
在您的情况下,int
和null
都要求隐式转换成为int?
,因此无效。
您需要更改代码,以便一方是int?
,而另一方可以隐式转换为int?
。简单的方法是将null
替换为new int?()
,如下所示:
int? b = (a != 0 ? a : new int?());
这只需要一次隐式转换(int
到int?
)。
答案 5 :(得分:0)
对于条件运算符,这几乎是one我的问题的重复。它不是空的,它确实是:
。
接受的答案非常好,来自Eric Lippert,他是C#编译团队的成员。