为什么C#编译器不会因为这种明显的"坏"转换而抱怨溢出?

pen*_*ake 9 .net c# compiler-construction clr overflow

我无法理解为什么下面的代码编译.

public void Overflow()
{
    Int16 s = 32767;
    s = (Int16)  (s + 1);
}
Run Code Online (Sandbox Code Playgroud)

在编译时,很明显(s + 1)不再是Int16,因为我们知道s的值.

CLR允许转换为:

  • 为了自己的类型
  • 或者任何基类型(因为它是安全的)

因为Int32不是Int16,而Int16不是Int32的基本类型.

问题:为什么编译器不会因为上面的转换而失败?你能从CLR和编译器的角度解释它吗?

谢谢

Jon*_*eet 12

表达式的类型s + 1Int32- Int32在执行加法之前将两个操作数转换为.所以你的代码相当于:

public void Overflow()
{
    Int16 s = 32767;
    s = (Int16)  ((Int32) s + (Int32) 1);
}
Run Code Online (Sandbox Code Playgroud)

所以溢出实际上只发生在显式转换中.

或者,换句话说:因为语言规范是这样说的.你应该描述一个:

  • 为什么您认为编译器违反了语言规范
  • 您对语言规范提出的确切更改

编辑:只是为了使事情变得非常清楚(基于你的评论),编译器不允许这样:

s = s + 1;
Run Code Online (Sandbox Code Playgroud)

sInt16 任何的值s可能会被称为是.没有Int16 operator+ (Int16, Int16)运算符 - 如C#4规范第7.8.4节所示,整数加法运算符是:

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)

  • @pencilCake:`s = s + 1;`不编译,因为`s + 1`的结果是`Int32`并且没有从`Int32`到`Int16`的隐式转换. (3认同)