2012-01-29 48 views
6

下面的程序将无法编译:为什么const int会隐式转换为一个字节,但是变量int不会呢?

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一个常量,那么它会编译:

class Program 
    { 
     public const int x = 50; 

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

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

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

这让自认为这是合法的,我以什么编译器在这里做更多的好奇。

+0

'const'值被替换。 – 2012-01-29 01:20:03

+0

尝试与'公共const int x = 350;' – 2012-01-29 01:29:02

+0

相关:http://stackoverflow.com/questions/9008637/why-does-this-implicit-conversion-from-int-to-uint-work – CodesInChaos 2012-01-29 16:53:59

回答

5

编译器会像处理该数字那样处理常量,但需要进行隐式转换。

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

0

基本上,它的区别在于,当编译器知道编译时的值时,允许强制转换的是较大数字类型的值在较小数字类型的允许范围内。如果编译器不知道这是否是这种情况,那么除非您使用显式转换来确保它在程序运行时在该范围内,否则不会被允许。尽管我们知道x的值在它的声明和使用之间不太可能发生变化,但是确定地知道它不会改变需要编译器不会尝试的复杂分析(并且实际上不可能总是得到正确的)。如果一个变量不是const,那么编译器不会推断它的实际值。

2

对于一个字节,非常量值可能过大,而常量值是常数,并且保证在此情况下低于阈值。

0

答案是:因为const通过预处理器例程变成了文字,并且被解释为'代码',而变量不是。

1

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

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

6

我把你转到6.1节。的C#4规范,其中规定的9:

int类型的常量表达式可以被转换为类型为sbyte,字节,短,USHORT,uint或ulong,则所提供的常量表达式的值是内目标类型的范围。

你的问题是:

该编译器创建我的飞行常量的“字节”的版本,或者它编译它,就好像我已经制定了一个明确的转换,因为它认为一个字节的常量值“安全”?

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

+0

啊,那从规范引用正是我所期待的。谢谢! – 2012-01-29 19:08:56

相关问题