【发布时间】:2015-04-19 06:24:53
【问题描述】:
将int 文字分配给byte 变量是合法的:
byte b = 123; // legal
但是,将int 变量分配给byte 变量是非法的:
int i = 123;
byte b = i; // illegal
【问题讨论】:
将int 文字分配给byte 变量是合法的:
byte b = 123; // legal
但是,将int 变量分配给byte 变量是非法的:
int i = 123;
byte b = i; // illegal
【问题讨论】:
因为当您分配文字(常量值)时,编译器可以证明该值适合字节。当您分配一个变量时,它不能。
如果您分配一个常量,编译器会非常乐意编译,因为它可以确认值在 (0 - 255) 的范围内,这是 byte 的有效范围。
例如下面的代码编译没有任何问题。
const int i = 123;
byte b = i;
【讨论】:
accepted answer 不太正确。
在第二个示例中,当然编译器可以使用简单的静态分析来证明该值是合适的。语言规范不允许这样做。
对于像 IL Jitter 这样的编译器来说,证明这一点是微不足道的,而且在很多情况下都可以证明这一点。 C# 编译器无法接受这一点,因为它违反了规范。
该答案中给出的示例是允许的,因为规范允许,而不仅仅是因为有证据。
const int i = 123;
byte b = i;
让我们看一下规范,ECMA-334 第 11.2.10 节(您可能会发现 microsoft.com 更易于浏览)
11.2.10 隐式常量表达式转换
隐式常量表达式转换允许以下转换:
int类型的常量表达式(§12.20) 可以转换为sbyte、byte、short、ushort、uint或@ 类型987654333@,前提是 constant-expression 的值在目标类型的范围内。
让我们 take a look at §12.20 了解 constant-expression 的定义:
常量表达式
constant_expression 是可以在编译时完全计算的表达式。
常量表达式必须是
null文字或具有以下类型之一的值:sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、object、string或任何枚举类型。常量表达式中只允许以下结构:
- 文字(包括
null文字)。- 对
const类和结构类型成员的引用。- 对枚举类型成员的引用。
- 对
const参数或局部变量的引用- 带括号的子表达式,它们本身就是常量表达式。
- 转换表达式,前提是目标类型是上面列出的类型之一。
checked和unchecked表达式- 默认值表达式
- 表达式名称
- 预定义的
+、-、!和~一元运算符。- 预定义的
+,-,*,/,%,<<,>>,&,|,@98764367@,@9876533 987654370@、==、!=、<、>、<=和>=二元运算符,前提是每个操作数都属于上面列出的类型。?:条件运算符。
那么,回到问题中的第一个示例
byte b = 123;
值123 是一个字面整数,是一个常量表达式,适合byte,因此可以隐式转换为byte。
接下来,
int i = 123;
byte b = i;
这里i 的值不是一个常量表达式,因此它不能隐式转换为byte。编译器无法允许这样做,因为规范不允许这样做。
最后是另一个答案中的示例
const int i = 123;
byte b = i;
这里,i 是一个常量表达式(因为它是对const 的引用),它的值已知适合byte,因此它是允许的按规范。
【讨论】:
In the second example, of course the compiler could prove that the value will fit, using simple static analysis. 它也不能因为调试器。没有什么能阻止你摆弄调试器中的值。因此,在这方面,现状是有道理的。
True, but in optimized Release build you might have thought it would do so. 我认为 Release 版本不会对 Debug 版本发出不同的警告——尽管我可能是错的。我是否同意总体的答案?是的,我愿意。