【问题标题】:C# Bitwise OR needs casting with byte *sometimes* [duplicate]C#按位或需要使用字节*有时*进行强制转换[重复]
【发布时间】:2009-10-14 18:44:45
【问题描述】:

我在 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();    
    }
}

谢谢。

【问题讨论】:

    标签: c# bitwise-operators


    【解决方案1】:

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

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

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

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

    4) 复合赋值运算符会自动将强制类型转换插入操作数类型,作为其操作的一部分,正是为了使 b |= 之类的表达式按您的预期工作。

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

    【讨论】:

      【解决方案2】:

      怀疑是行:

      byte b = BIT_ZERO_SET | BIT_ONE_SET;
      

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

      行:

      //b = b | BIT_TWO_SET;
      

      未编译,因为按位 OR 运算符提升其元素并计算为 int,而不是字节。由于它涉及运行时值 (b),因此它不能像前行那样编译为常量赋值,并且需要强制转换。

      【讨论】:

      • +1,是的,编译器将在编译时计算常量表达式。这就解释了为什么第一个作业没有给出错误。
      • @Godeke:你说什么和他不一样?他是说byte 上的按位OR 的结果值是一个int。
      • 整个常量表达式是一条红鲱鱼,仅此而已。 |将从不返回一个不进行强制转换的字节,它只返回 int、uint、long 或 ulong。
      • EMCA-334 14.10 逻辑运算符
      • 不幸的是,同样的技巧不能用于unsetting位,因为这需要~BIT_TWO_SET。这甚至不适用于常量,无论是有符号的还是无符号的(因为隐式转换规则的细节)
      【解决方案3】:

      这绝对是奇怪的,但是发生了什么,b|BIT_TWO_SET 的结果是一个整数。

      这可行:b = (byte)(b | BIT_TWO_SET);,因为在这种情况下结果是一个 int。

      此外,您可以将该行替换为:b |= BIT_TWO_SET;,这样可以正常工作。

      【讨论】:

      • 我不知道有一个 |=。谢谢!
      • x |= yx &= ~y 是您的位操作朋友。
      【解决方案4】:
              b = (byte)(b | BIT_TWO_SET);
      

      至少在 Visual Studio 2008 对 2.0 中,您需要进行强制转换以使其编译。看来|将字节提升为 int,您必须手动将其再次降级。

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

      【讨论】:

      • 是的,我意识到这一点后更改了我的帖子。谢谢。
      【解决方案5】:

      而不是使用

       b = b | BIT_TWO_SET;
      

      使用这个:

       b |= BIT_TWO_SET;
      

      很有趣吧。

      【讨论】:

        猜你喜欢
        • 2010-10-29
        • 2012-10-01
        • 1970-01-01
        • 2021-03-19
        • 1970-01-01
        • 2011-09-15
        • 1970-01-01
        相关资源
        最近更新 更多