C#按位OR有时需要使用byte *进行转换*

时间:2009-10-14 18:44:45

标签: c# bitwise-operators

我在C#编译器中发现了奇怪的情况。为什么需要下面的演员?

using System;

class Program
{
    private const byte BIT_ZERO_SET = 1;
    private const byte BIT_ONE_SET = 2;
    private const byte BIT_TWO_SET = 4;

    static void Main(string[] args)
    {
        byte b = BIT_ZERO_SET | BIT_ONE_SET;
        Console.WriteLine(b);

        //Does not compile, says needs to cast to int.
        //b = b | BIT_TWO_SET;

        //Compiles...ugly
        b = (byte)(b | BIT_TWO_SET);
        Console.WriteLine(b);

        Console.WriteLine("Press enter.");
        Console.ReadLine();    
    }
}

感谢。

5 个答案:

答案 0 :(得分:13)

这里的各种答案通常都是正确的,但却有很多不同的事实遍布各处。相关要点是:

1)byte |的结果byte是一个int,因为没有|运算符在字节上定义。

2)仅涉及整数编译时常数的计算被视为“已检查”算术;也就是说,编译器会验证常量结果是否不会溢出,依此类推。这个事实的一个令人愉快的结果是,将编译时常量整数赋值给变量或较小类型的常量会自动验证常量整数是否适合较小的类型。如果是,则允许在没有显式强制转换的情况下进行分配。如果没有,则发生编译时错误。 (如果要覆盖此行为,请使用“未选中”表达式。)

3)从int到byte的非常量表达式的赋值需要强制转换,因为编译器无法知道结果肯定适合字节。

4)复合赋值运算符会自动将转换作为操作的一部分插入到操作数类型中,这样就可以使b | =等表达式按照您的预期工作。

这四个事实应该解释你们所指出的所有行为。

答案 1 :(得分:7)

这绝对很奇怪,但正在发生的事情是,b|BIT_TWO_SET的结果是一个整数。

这有效:b = (byte)(b | BIT_TWO_SET);因为在这种情况下结果是int。

此外,您可以将该行替换为:b |= BIT_TWO_SET;,该作品可用。

答案 2 :(得分:6)

怀疑是这条线:

byte b = BIT_ZERO_SET | BIT_ONE_SET;

实际上是由C#编译器处理为b的常量值赋值,而不是按位运算 - 它可以这样做,因为表达式的右侧在编译时是完全定义的。

该行:

//b = b | BIT_TWO_SET;

未编译,因为按位OR运算符提升其元素并计算为int,而不是字节。由于它涉及运行时值(b),因此无法将其编译为常规赋值,如之前的行,并且需要转换。

答案 3 :(得分:2)

        b = (byte)(b | BIT_TWO_SET);

是您需要进行强制转换才能进行编译,至少在Visual Studio 2008中是针对2.0进行编译的。看来|将字节提升为int,你必须手动将其降级。

是的......超过标准的快速运行表明|返回int(或uint或long或ulong)。

答案 4 :(得分:0)

而不是使用

 b = b | BIT_TWO_SET;

使用它:

 b |= BIT_TWO_SET;

搞笑吧。