我有这段代码。
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });
当我尝试编译时,我得到:
无法隐式转换类型'int' '字节'。显式转换 存在(你是否错过演员表?)
为什么会这样?不应该|两个字节给出一个字节?以下两项工作,确保每个项目都是一个字节。
Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
答案 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。