为什么const int隐式地转换为一个字节,而一个变量int不?

时间:2012-01-29 01:18:25

标签: c# .net clr

以下程序无法编译:

   class Program
   {
      static void Main(string[] args)
      {
         int x = 50;
         Byte[] y = new Byte[3] { x, x, x };
      }
   }

毫不奇怪,我会收到错误Cannot implicitly convert type 'int' to 'byte'

但是,如果我使x成为const,那么它将编译:

   class Program
   {
      public const int x = 50;

      static void Main(string[] args)
      {
         Byte[] y = new Byte[3] { x, x, x };
      }
   }

我很好奇这里发生了什么。如果int无法隐式地转换为字节,编译器是否会动态创建我的const的“字节”版本,或者它是否编译它就好像我已经进行了显式转换,因为它认为一个字节的常量值“安全”?也许编译器将此解释为我写的:

Byte[] y = new Byte[3] { 50, 50, 50 };

由于这是合法的,我对编译器在这里所​​做的事情更感兴趣。

6 个答案:

答案 0 :(得分:6)

我推荐你参考C#4规范的第6.1.9节,其中规定:

  

如果常量表达式的值在目标类型的范围内,则int类型的常量表达式可以转换为sbyte,byte,short,ushort,uint或ulong类型。

你的问题是:

  

编译器是否会动态创建我的const的“字节”版本,或者它是否编译它就好像我已经进行了显式转换,因为它认为一个字节的常量值“安全”?

我不明白这两件事之间的区别;对我来说,它们听起来是一回事。

答案 1 :(得分:5)

编译器只会将常量视为在那里编写数字,但需要进行隐式转换。

在您的第三个代码段中,这三个50都是System.Int32。将鼠标悬停在其上并阅读Visual Studio中的工具提示。为什么编译器错误不在这里?因为编译器在编译时知道该值并且知道它将适合byte

答案 2 :(得分:2)

对于字节,非常量值可能太大,而常量值是常量,并且在这种情况下保证低于阈值。

答案 3 :(得分:1)

常量在编译时被“烘焙”。

如何编译常量的一个值得注意的结果是,如果针对程序集进行编译,它将在编译时使用常量值。如果稍后在运行时绑定不同版本的程序集,它将使用原始常量,即使它们在新版本的程序集中已更改。这也适用于Enum常量。故事的寓意是(公共)常数值确实应该是恒定的;如果有可能发生有意义的更改,请改用静态只读字段。

答案 4 :(得分:0)

基本上它归结为不同之处在于,当编译器在编译时知道该值时,则允许强制转换是较大数字类型的值在较小数字类型的允许范围内。如果编译器不知道是否是这种情况,那么除非你使用显式转换来确保程序运行时它将在该范围内,否则不允许这样做。

尽管我们知道x的值在声明和使用之间不太可能发生变化,但是肯定知道它不会改变需要编译器不会尝试的复杂分析(并且实际上不可能总是这样做)得到正确的)。如果变量不是const,则编译器不会对其实际值进行推断。

答案 5 :(得分:0)

答案是:因为const由预处理程序例程变为文字,并且被解释为“代码”,而变量则不是。