【问题标题】:Why assigning an int literal to a byte variable is legal?为什么将 int 文字分配给字节变量是合法的?
【发布时间】:2015-04-19 06:24:53
【问题描述】:

int 文字分配给byte 变量是合法的:

byte b = 123;   // legal

但是,将int 变量分配给byte 变量是非法的:

int i = 123;
byte b = i;     // illegal

【问题讨论】:

标签: c# .net


【解决方案1】:

因为当您分配文字(常量值)时,编译器可以证明该值适合字节。当您分配一个变量时,它不能。

如果您分配一个常量,编译器会非常乐意编译,因为它可以确认值在 (0 - 255) 的范围内,这是 byte 的有效范围。

例如下面的代码编译没有任何问题。

const int i = 123;
byte b = i; 

【讨论】:

    【解决方案2】:

    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) 可以转换为sbytebyteshortushortuint 或@ 类型987654333@,前提是 constant-expression 的值在目标类型的范围内。

    让我们 take a look at §12.20 了解 constant-expression 的定义:

    常量表达式

    constant_expression 是可以在编译时完全计算的表达式。

    常量表达式必须是 null 文字或具有以下类型之一的值:sbytebyteshortushortintuintlongulongcharfloatdoubledecimalboolobjectstring 或任何枚举类型。常量表达式中只允许以下结构:

    • 文字(包括null 文字)。
    • const 类和结构类型成员的引用。
    • 对枚举类型成员的引用。
    • const参数或局部变量的引用
    • 带括号的子表达式,它们本身就是常量表达式。
    • 转换表达式,前提是目标类型是上面列出的类型之一。
    • checkedunchecked 表达式
    • 默认值表达式
    • 表达式名称
    • 预定义的+-!~ 一元运算符。
    • 预定义的+,-,*,/,%,<<,>>,&,|,@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 版本发出不同的警告——尽管我可能是错的。我是否同意总体的答案?是的,我愿意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2023-03-22
    • 2021-09-09
    • 1970-01-01
    • 2018-10-08
    • 2021-10-15
    • 2014-06-28
    相关资源
    最近更新 更多