在C#中从短到节转换时会发生什么?

Fio*_*ite 11 c# byte casting short

我有以下代码:

short myShort = 23948;
byte myByte = (byte)myShort;
Run Code Online (Sandbox Code Playgroud)

现在我没想到myByte要包含值23948.我猜它会包含255(我相信一个字节的最大值).

然而,它包含140,它让我想知道为什么; 幕后实际发生了什么?

请注意,我不是在找人解决23948无法容纳的问题,我只想知道底层实现

Pau*_*sik 15

Short是2字节类型,字节是单字节.当你从两个字节转换为一个字节时,你强迫系统使事情适合,原始字节之一(最重要的)被丢弃,数据丢失.从23948(二进制:0101 1101 1000 1100)的值剩下的是140,二进制转换为1000 1100.所以你要从:

0101 1101 1000 1100 (2 byte decimal value 23948)
Run Code Online (Sandbox Code Playgroud)

至:

          1000 1100 (1 byte decimal value 140)
Run Code Online (Sandbox Code Playgroud)

您只能通过显式转换来执行此操作.如果您尝试在没有强制转换的情况下为字节分配短路,则编译器会因为可能丢失数据而引发错误:

无法将类型'short'隐式转换为'byte'.存在显式转换(您是否错过了演员?)

另一方面,如果从一个字节转换为一个short,你可以隐式地执行它,因为没有数据会丢失.

using System;
public class MyClass
{
    public static void Main()
    {
        short myShort = 23948;
        byte myByte = (byte)myShort; // ok
        myByte = myShort; // error: 

        Console.WriteLine("Short: " + myShort);
        Console.WriteLine("Byte:  " + myByte);

        myShort = myByte; // ok

        Console.WriteLine("Short: " + myShort);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用算术溢出和未检查的上下文:

using System;
public class MyClass {
    public static void Main() {
        unchecked {
            short myShort = 23948;
            byte myByte = (byte)myShort; // ok
            myByte = myShort; // still an error
            int x = 2147483647 * 2; // ok since unchecked
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 6

基本上它只需要最后8位...但一般来说,当你发现一些令你惊讶的行为时,下一步应该是查阅规范.从第6.2.1节开始,加上我的额外重点,针对在这种情况下相关的情况.

对于从整数类型到另一个整数类型的转换,处理取决于发生转换的溢出检查上下文(第7.6.12节):

  • 在已检查的上下文中,如果源操作数的值在目标类型的范围内,则转换成功,但如果源操作数的值超出目标类型的范围,则抛出System.OverflowException.
  • 在未经检查的上下文中,转换始终成功,并按如下方式进行.
    • 如果源类型大于目标类型,则通过丢弃其"额外"最高有效位来截断源值.然后将结果视为目标类型的值.
    • 如果源类型小于目标类型,则源值可以是符号扩展或零扩展,以使其与目标类型的大小相同.如果源类型已签名,则使用符号扩展; 如果源类型是无符号的,则使用零扩展.然后将结果视为目标类型的值.
    • 如果源类型与目标类型的大小相同,则源值将被视为目标类型的值.