为什么从int到uint的隐式转换有效?

Yuc*_*uck 13 .net c# compiler-construction type-conversion implicit-conversion

使用Casting null并不能作为灵感编译,并且来自Eric Lippert的评论:

这表明了一个有趣的案例."uint x =(int)0;" 即使int不能隐式转换为uint也会成功.

我们知道这不起作用,因为object无法分配到string:

string x = (object)null;
Run Code Online (Sandbox Code Playgroud)

但这确实如此,但直觉上它不应该:

uint x = (int)0;
Run Code Online (Sandbox Code Playgroud)

为什么编译器允许这种情况下,int不隐式转换为uint

Eri*_*ert 26

C#语言将整数常量转换视为非常特殊; 这是规范的第6.1.9节:

如果constant-expression的值在目标类型的范围内,则int类型的常量表达式可以转换为sbyte,byte,short,ushort,uint或ulong类型.如果常量表达式的值不是负数,则long类型的常量表达式可以转换为ulong类型.

这允许您执行以下操作:

byte x = 64;
Run Code Online (Sandbox Code Playgroud)

否则需要一个丑陋的显式转换:

byte x = (byte)64; // gross
Run Code Online (Sandbox Code Playgroud)

  • +1非常酷.不过,我已经和`// yuck`一起去了;) (12认同)
  • @dlev:后者.将int类型的常量表达式转换为int仍然是常量表达式. (3认同)
  • @JonH:这是一个合理的问题.仅当表达式是int*类型的*常量表达式且结果在范围内时,该规则才适用.在这种情况下,(int)0*是*常量表达式.我注意到我们过去曾犯过这些错误.例如,规范说*文字零*可以隐式转换为任何枚举.但我们也允许"E e = 0 + 0;" 尽管"0 + 0"不是*"字面零"这一事实 - 它是两个字面上的零,它们之间有加号. (2认同)
  • @gdoron:它显然不是*变量*因为**变量根据定义是存储位置**.它被归类为*值*; a*常量表达式*是一种特殊的*值*. (2认同)

Wou*_*ort 9

以下代码将失败,并显示消息"无法将类型'int'隐式转换为'uint'.存在显式转换(您是否错过了转换?)"

int y = 0;
uint x = (int)y;
Run Code Online (Sandbox Code Playgroud)

这将失败:"常量值'-1'无法转换为'uint'"

uint x = (int)-1;
Run Code Online (Sandbox Code Playgroud)

因此,唯一的原因uint x = (int)0;是因为编译器看到0(或任何其他值> 0)是一个编译时常量,可以转换为uint

  • @BoltClock可以在编译时转换常量表达式,以便确实删除了强制转换. (3认同)