编译器中的错误或误解?或短裤上的操作员

jmo*_*eno 5 c# bitwise-operators roslyn c#-6.0

我有一行代码在VS2015中给我一个警告信息(CS0675),但在2013年没有.

shortValue |= (short)anEnum;
Run Code Online (Sandbox Code Playgroud)

警告CS0675在符号扩展操作数上使用按位或运算符; 首先考虑转换为较小的无符号类型.编译器隐式地扩展并对变量进行符号扩展,然后在按位OR运算中使用结果值.这可能会导致意外行为.

显然正在发生的是enum和short被扩展为int,或者运算符应用,然后结果将结果分配给short.

如果我将代码更改为shortValue = shortValue | (short)anEnum;我得到编译器错误CS0266.但是按位OR应该对短路有效(在我认为的两种情况下).如果我将鼠标悬停在|它上面显示为一个int操作符,我是否遗漏了某些东西或者我应该将其报告为错误?

PS:我知道我可以通过使用=而不是|=将结果转换为简短来消除警告/错误.

i3a*_*non 5

如果你看看C#规格(特别是在"整数逻辑运算符"),你会看到有只用于定义int,uint,long,ulong对于逻辑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);
Run Code Online (Sandbox Code Playgroud)

另外,在Bit twiddling中:警告CS0675是什么意思?Eric Lippert说:

"有按位或运算符定义int,uint,longulong"

运算符有效short,但仅限于短值可以扩展到的意义int.但是,该运算符的返回值是(至少)a int.

因此,从技术上讲,根据规范,这似乎不是一个错误,因为使用|=确实将签名值扩展为int,这给出了一个警告,并且常规|结果int需要被转换为分配给一个short.

但是,由于编译器实际上可以知道两个操作数最初都是shorts,所以两者都被扩展到int并且结果最终会被存储回到short它中,操作数被扩展并不重要.演员int从而失去了延期short.

因此,VS2013编译器的警告比VS2015编译器更智能,或VS2015修复了一个错误,并警告VS2013失败的地方.只有编译器背后的人可以回答这个问题,但我认为它确实是一个错误(编辑:它是).

  • @jmoreno它显然是修复的:https://github.com/dotnet/roslyn/issues/4027 (2认同)