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

Nat*_*ate 5 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();    
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

Eri*_*ert 14

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

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

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

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

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

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


Eri*_*ich 7

这绝对是奇怪的,但正在发生的b|BIT_TWO_SET是整数的结果.

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

此外,您可以用以下内容替换该行:b |= BIT_TWO_SET;哪个有效.


LBu*_*kin 6

怀疑是行:

byte b = BIT_ZERO_SET | BIT_ONE_SET;
Run Code Online (Sandbox Code Playgroud)

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

这条线:

//b = b | BIT_TWO_SET;
Run Code Online (Sandbox Code Playgroud)

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

  • 整个不断表达的东西是红鲱鱼,就是这样.| will*never*在没有强制转换的情况下返回一个字节,它只返回int,uint,long或ulong. (3认同)