我试图弄清楚为什么在以下示例中需要强制转换:
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在执行此操作时应考虑可以为空的类型。
我想了解这些编译器错误背后是否存在实际推理。
答案 0 :(得分:6)
表达式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);
原因是第一次赋值是在编译时计算的,因为它只包含常量。在这种情况下,隐式常量表达式转换规则适用:
•如果constant-expression的值在目标类型的范围内,则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's comments。
第二个例子需要将Nullable<>
视为特殊情况,就像您已经注意到的那样。