负号应用在short类型上会变成int类型?

10
在下面的内容中:
public class p
{
  short? mID;
  short? dID;
}

short id = p.mID ?? -p.dID.Value;

编译器报错:

错误 21:无法隐式将类型“int”转换为“short”。存在显式的转换(是否遗漏了一个强制转换?)

我必须将代码更改为以下内容才能正常工作:

short id = p.mID ?? (short)-p.dID.Value;

就好像编译器在执行 (int)0 - p.dID.Value 这样的操作,或者是 Int16.operator - 返回了 Int32。

2个回答

14
我将您引用到规范的7.6.2节,其中指出:


对于形式为-x的操作,会应用一元运算符重载解析来选择特定的运算符实现。操作数被转换为所选运算符的参数类型,结果类型为运算符的返回类型。预定义的取反运算符包括:

整数取反:

int operator –(int x);
long operator –(long x);
结果是通过从零减去 x 计算得出的。如果 x 的值是操作数类型的最小可表示值 (int 为 -2^31 或 long 为 -2^63),则 x 的数学取反在操作数类型内是不可表示的。如果这发生在一个已检查的上下文中,则会抛出 System.OverflowException;如果发生在一个未经检查的上下文中,则结果是操作数的值,而溢出不被报告。
如果取反运算符的操作数是 uint 类型,则将其转换为 long 类型,结果的类型为 long。例外情况是允许将 int 值 -2147483648 (-2^31) 写成十进制整数字面量的规则。
如果取反运算符的操作数是 ulong 类型,则会发生编译时错误。例外情况是允许将 long 值 -9223372036854775808 (-2^63) 写成十进制整数字面量的规则。
浮点数取反:
float operator –(float x);
double operator –(double x);

结果是将x的值反转其符号。如果x是NaN,则结果也是NaN。

十进制取反:

decimal operator –(decimal x);

该结果是通过从零中减去 x 计算得出的。十进制取反相当于使用类型 System.Decimal 的一元减号运算符。


正如您所看到的,short类型上没有定义一元减号运算符;重载决策会选择int类型的一元减号运算符,因为它是所有可用一元减号运算符中最匹配的一个。


2
非常好的答案,谢谢!不过我确实想知道为什么短整型没有定义一元负运算符。有什么理论吗? - rabidpebble
@rabidpebble 当然,这同样适用于所有二元运算符。例如 p.mID + p.mIDp.mID / p. mIDp.mID & p.mID 等许多其他运算符,即使两个操作数都是 short 类型,结果也将是 int 类型。 - Jeppe Stig Nielsen
2
对于那些寻找7.6.2版本的人来说,在ECMA-334的第5版中,该部分已经移至12.8.3。 - alx9r

3

没有一元负号运算符可以接受short类型的值。相反,重载决议会选择一元负号运算符的int版本并进行隐式转换。


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