C#中的OR-ing字节给出了int

时间:2009-07-31 20:14:05

标签: c# types logic bit-manipulation byte

我有这段代码。

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });

当我尝试编译时,我得到:

  

无法隐式转换类型'int'   '字节'。显式转换   存在(你是否错过演员表?)

为什么会这样?不应该|两个字节给出一个字节?以下两项工作,确保每个项目都是一个字节。

Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });

3 个答案:

答案 0 :(得分:17)

这就是C#中的设计方式,事实上,它一直追溯到C / C ++ - 后者还将操作数提升为int,你通常不注意因为{{1}转换是隐式的,而不是C#。这不仅适用于int -> char,也适用于所有算术和按位操作数 - 例如添加两个|也会为您提供byte。我在这里引用规范的相关部分:

  

发生二进制数字促销   预定义的操作数+, - ,   *,/,%,&,|,^,==,!=,>,<,> =,和< =二元运算符。二进制   数字促销隐式转换   这两种操作数都属于普通类型,   如果是非关系型的   运营商也成为了结果   操作类型。二进制数字   促销包括应用   遵循规则,按顺序排列   出现在这里:

     
      
  • 如果任一操作数是   键入十进制,另一个操作数是   转换为十进制类型,或者a   如果另一个发生编译时错误   操作数的类型为float或double。

  •   
  • 否则,如果任一操作数是   类型为double,另一个操作数是   转换为double类型。

  •   
  • 否则,   如果任一操作数的类型为float,   另一个操作数转换为类型   浮。

  •   
  • 否则,如果是任一操作数   是ulong类型,另一个操作数是   转换为ulong类型,或者a   如果另一个发生编译时错误   操作数的类型为sbyte,short,int,   或者长。

  •   
  • 否则,如果是   操作数是long类型,另一个是long   操作数转换为long类型。

  •   
  • 否则,如果任一操作数是   输入uint,另一个操作数是   输入sbyte,short或int,两者   操作数转换为long类型。

  •   
  • 否则,如果任一操作数是   输入uint,另一个操作数是   转换为uint类型。

  •   
  • 否则,   两个操作数都转换为类型   中间体

  •   

我不知道这个的确切理由,但我可以考虑一个。特别是对于算术运算符,人们让int突然等于(byte)200 + (byte)100可能会有点令人惊讶,即使在仔细考虑所涉及的类型时它是有意义的。另一方面,44通常被认为是对大多数典型数字的算术“足够好”的类型,因此通过将两个参数都提升到int,您会得到一种“正常工作”的行为。最常见的情况。

至于为什么这个逻辑也适用于按位运算符 - 我想这主要是为了保持一致性。它产生一个简单的规则,对于所有非布尔二进制类型来说是常见的。

但这都是猜测。 Eric Lippert可能是至少要问这个C#决定的真正动机的人(尽管如果答案只是“它是如何在C / C ++和Java中完成的,那将是有点无聊的,而且它已经足够好了按规则统治,所以我们认为没有理由改变它“)。

答案 1 :(得分:6)

文字0x80的类型为“int”,因此您不是字节。

你可以将它传递给byte []只能起作用,因为0x80(作为文字)它在字节范围内。

编辑:即使将0x80强制转换为一个字节,代码仍然无法编译,因为oring字节仍然会给出int。要对其进行编译,必须强制转换结果:(byte)(0x80|dup)

答案 2 :(得分:4)

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });

两个字节上的按位Or(|)的结果总是一个int。