需要使用 C# 三元条件运算符进行转换

Required casting using C# ternary conditional operator

我试图找出为什么在以下示例中需要转换:

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

第二个例子对我来说更有意义。我知道编译器无法确定 = 右侧的表达式类型,但 IMO 这样做时应该考虑可为 null 的类型。

我想了解这些编译器错误背后是否存在实际原因。

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

If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

另一个问题是为什么,例如,文字 0 可以分配给 short 变量而无需转换:

short i = 0;

并且必须转换三元运算符的结果:

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

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

• A constant-expression (§7.19) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.

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

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's comments

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