关于类型:C#中的OR-ing字节给出了int

OR-ing bytes in C# gives int

本问题已经有最佳答案,请猛点这里访问。

我有这个密码。

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

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

Cannot implicitly convert type 'int'
to 'byte'. An explicit conversion
exists (are you missing a cast?)

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

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


C是这样设计的,事实上,它可以追溯到C/C++——后者也将操作数提升到EDCOX1(1),通常你不会注意到,因为EDCOX1×2的转换是隐式的,而不是C语言。这不仅适用于|,而且也适用于所有算术和位操作数-例如,添加两个byte将给您一个int。我将在这里引用规范的相关部分:

Binary numeric promotion occurs for
the operands of the predefined +, –,
*, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • If either operand is of
    type decimal, the other operand is
    converted to type decimal, or a
    compile-time error occurs if the other
    operand is of type float or double.

  • Otherwise, if either operand is of
    type double, the other operand is
    converted to type double.

  • Otherwise,
    if either operand is of type float,
    the other operand is converted to type
    float.

  • Otherwise, if either operand
    is of type ulong, the other operand is
    converted to type ulong, or a
    compile-time error occurs if the other
    operand is of type sbyte, short, int,
    or long.

  • Otherwise, if either
    operand is of type long, the other
    operand is converted to type long.

  • Otherwise, if either operand is of
    type uint and the other operand is of
    type sbyte, short, or int, both
    operands are converted to type long.

  • Otherwise, if either operand is of
    type uint, the other operand is
    converted to type uint.

  • Otherwise,
    both operands are converted to type
    int.

我不知道确切的理由,但我可以考虑一个。尤其是对于算术运算符来说,即使仔细考虑所涉及的类型,使(byte)200 + (byte)100突然等于44,这可能会让人有点惊讶。另一方面,int通常被认为是对大多数典型数字进行算术"足够好"的一种类型,因此,通过将两个参数都提升到int中,对于大多数常见的情况,您会得到一种"只起作用"的行为。

至于为什么这个逻辑也被应用于位运算符,我想这主要是为了一致性。它产生了一个简单的规则,对于所有非布尔二进制类型都是通用的。

但这都是猜测。Eric Lippert可能会问一个关于这一决定背后的真正动机至少是C(尽管答案是简单的"它是如何在C/C++和Java中完成的,它是一个足够好的规则,所以我们没有理由改变它")。


字面值0x80的类型为"int",因此您不是ORing字节。

您可以将其传递给byte[]的方法只起作用,因为0x80(作为文本)在byte的范围内。

编辑:即使将0x80转换成一个字节,代码仍然不会编译,因为ORing字节仍然会给int。要编译它,OR的结果必须转换为:(byte)(0x80|dup)


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

两个字节上的按位或()的结果始终是int。