如何使用可空整数的条件运算符

8
一个小问题。大家有什么想法为什么这个不起作用吗?
int? nullableIntVal = (this.Policy == null) ? null : 1;

我想要的效果是:如果左侧表达式为True,则返回null,否则返回1。看起来很简单,但会导致编译错误。

条件表达式的类型无法确定,因为nullint之间没有隐式转换。

如果我用任何有效的int替换? null : 1中的null,则不会出现问题。

5个回答

21

是的 - 编译器无法为条件表达式找到适当的类型。忽略你将其分配给一个int?的事实 - 编译器不使用该信息。因此,表达式为:

(this.Policy == null) ? null : 1;

这个表达式的类型是什么?语言规范规定它必须是第二个操作数的类型或者第三个操作数的类型。因为null没有类型,所以它必须是int(第三个操作数的类型)- 但是从nullint没有转换,所以失败了。

将任一操作数强制转换为int?即可解决问题,或者使用另一种表示空值的方式 - 这些方式中的任何一种:

(this.Policy == null) ? (int?) null : 1;

(this.Policy == null) ? null : (int?) 1;

(this.Policy == null) ? default(int?) : 1;

(this.Policy == null) ? new int?() : 1;

我同意这有点麻烦。


来自 C# 3.0 语言规范的第 7.13 节:

条件运算符的第二个和第三个操作数控制条件表达式的类型。设 X 和 Y 分别为第二个和第三个操作数的类型,则有:

  • 如果 X 和 Y 是相同的类型,则条件表达式的类型就是该类型。

  • 否则,如果存在从 X 到 Y 的隐式转换 (§6.1),但不存在从 Y 到 X 的隐式转换,则条件表达式的类型为 Y。

  • 否则,如果存在从 Y 到 X 的隐式转换 (§6.1),但不存在从 X 到 Y 的隐式转换,则条件表达式的类型为 X。

  • 否则,无法确定任何表达式类型,编译时将出现错误。


精度和准确性非常高。 - this. __curious_geek
@David:在我得到语言规范的引用之前,它并不全面。现在我感觉好多了 :) - Jon Skeet
@Jon:确实是非常好的答案。从风格的角度来看,您认为哪个建议最好,为什么? - Doctor Jones
@DoctaJonez:我我可能会使用第一种形式...但每种形式都可以...而且没有一种形式特别好:( - Jon Skeet
感谢Jon提供精确的信息。然而,只是出于好奇,为什么编译器不应该将LHS操作数视为目标类型呢?例如,考虑Z =(expr to check)?X:Y;编译器是否应该检查X和Y是否都可以隐式转换为Z,而不是在X和Y中进行检查?如果不存在隐式转换,则必须将X或Y或两者都强制转换为与Z的类型匹配。我想这会更容易理解。 凭借我的有限知识,我不明白这是仅由C#设计还是有有效的原因不能这样做。 - Rajarshi
@Rajarshi:C#并不是那样工作的。编译器不应该检查这个,因为语言规范说它不应该——基本上,这种语言的设计是让表达式的类型在很大程度上独立于其上下文。 - Jon Skeet

4

试试这个:

int? nullableIntVal = (this.Policy == null) ? (int?) null : 1; 

2
也许你可以尝试以下方法:
default( int? );

使用非空替代 null


1
这个可以运行:int? nullableIntVal = (this.Policy == null) ? null : (int?)1;
原因(摘自评论):
错误信息是由于?:运算符的两个分支(null1)没有兼容的类型。 新解决方案的分支(使用null(int?)1)有。

一个 int 会被隐式转换为 int 吗?- 提问者在将 null 赋值给 int? 时遇到了问题。 - David Neale
错误信息是因为 ?: 运算符的两个分支(null1)没有兼容的类型。新解决方案的分支(使用 null(int?)1)是兼容的。 - Stephen Cleary
我认为他不希望它只是简单的1。 - Mohnkuchenzentrale
Stephen的答案是正确的。编译器错误是由于C#无法找到null1兼容的类型。因此,通过将1强制转换为int?,您使整个表达式与int?兼容。 - Sedat Kapanoglu

1

int? i = (true ? new int?() : 1);

int?i =(true?new int?():1);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接