需要使用c#三元条件运算符强制转换

本文关键字:三元 条件运算符 转换 | 更新日期: 2023-09-27 18:17:35

我想弄清楚为什么在下面的例子中需要强制类型转换:

bool test = new Random().NextDouble() >= 0.5;
short val = 5;
// Ex 1 - must cast 0 to short
short res = test ? 5 : 0;  // fine
short res = test ? val : 0;  // error
short res = test ? val : (short)0;  // ugly
// Ex 2 - must cast either short or null to short?
short? nres = test ? val : null;  // error
short? nres = test ? (short?)val : null;  // ugly
short? nres = test ? val : (short?)null;  // ugly
short? nres = test ? val : default(short?);  // ugly

第一个例子对我来说似乎很疯狂。如果short i = 0;编译,为什么编译器不能隐式地处理0(或任何其他有效的short值)作为short在上面的代码?

第二个例子对我来说更有意义。我理解编译器无法确定=右侧表达式的类型,但在我看来,它应该在这样做时考虑可空类型。

我想知道这些编译器错误背后是否有实际的原因。

需要使用c#三元条件运算符强制转换

表达式test ? val : 0编译得很好。你会在这一行得到一个错误,因为这个表达式的类型是int,你试图将它分配给一个short变量。这需要显式强制转换。来自c#语言规范:

如果存在从X到Y的隐式转换(第6.1节),但不存在从Y到X的隐式转换,则Y是条件表达式的类型。

另一个问题是,例如,为什么字面量0可以赋值给short变量而不需要强制转换:

short i = 0;

必须对三元操作符的结果进行强制转换:

bool test = new Random().NextDouble() >= 0.5;
short val = 5;
short i = (short)(test ? val : 0);

原因是第一次赋值是在编译时计算的,因为它只由常量组成。在这种情况下,应用隐式常量表达式转换规则:

•int类型的常量表达式(第7.19节)可以转换为sbyte、byte、short、ushort、uint或ulong类型,只要该常量表达式的值在目标类型的范围内。

如果所有操作数都是常量,也可以在编译时计算三元操作符:

short i = true ? 0 : int.MaxValue;

在任何其他情况下,应用更严格的运行时转换规则。以下3条语句都会导致编译错误:

int intVal = 0;
short shortVal = 0;
bool boolVal = true;
short i = true ? 0 : intVal;
short j = true ? shortVal : 0;
short k = boolVal ? 0 : 0;

参考Eric Lippert的评论

第二个示例需要将Nullable<>视为特例,就像您已经注意到的那样。