编译器错误或误解?或者穿短裤的接线员

Bug in compiler or misunderstanding? Or operator on shorts

我有一行代码在 VS2015 中给我一条警告消息 (CS0675),但在 2013 中没有。

shortValue |= (short)anEnum;

Warning CS0675 Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first. The compiler implicitly widened and sign-extended a variable, and then used the resulting value in a bitwise OR operation. This can result in unexpected behavior.

显然发生的事情是枚举和 short 被扩展为 int,应用 or 运算符,然后结果将结果分配给 short。

如果我将代码更改为 shortValue = shortValue | (short)anEnum;,我会收到编译器错误 CS0266。但是按位或应该对短裤有效(我相信在这两种情况下)。如果我将鼠标悬停在 | 上,它显示为 int 运算符,我是否遗漏了什么或者我应该将其报告为错误?

PS:我知道我可以通过使用 = 而不是 |= 并将结果转换为 short 来消除 warning/error。

如果您查看 C# 规范(特别是在 "Integer logical operators" 中),您会发现只有 intuintlongulong 对于逻辑 OR 运算符:

int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);

此外,在 Bit twiddling: What does warning CS0675 mean? 中,Eric Lippert 指出:

"There are bitwise-or operators defined on int, uint, long and ulong"

运算符对 short 有效,但仅在短值可以扩展到 int 的意义上。但是,该运算符的 return 值(至少)是 int.

所以,从技术上讲,根据规范,这似乎不是一个错误,因为使用 |= 确实将有符号值扩展为 int,这会发出警告,而常规 | 导致 int 需要转换为 short.

但是,因为编译器实际上可以知道两个操作数最初都是shorts,所以都扩展为int,结果最终会被存储回 short 扩展操作数并不重要。从 intshort 的转换将丢失扩展名。

因此,要么 VS2013 编译器的警告比 VS2015 编译器更聪明,要么 VS2015 修复了一个错误并在 VS2013 失败的地方发出警告。只有编译器背后的人才能回答这个问题,但我认为这确实是一个错误(编辑:and it is)。