【问题标题】:Why would someone use the << operator in an enum declaration?为什么有人会在枚举声明中使用 << 运算符?
【发布时间】:2013-07-27 02:58:47
【问题描述】:

我正在查看我目前在我的项目中的代码,发现如下内容:

public enum MyEnum
{
    open     = 1 << 00,
    close    = 1 << 01,
    Maybe    = 1 << 02,
    ........
}

&lt;&lt; 操作数是移位操作数,它将第一个操作数左移第二个操作数中指定的位数。

但是为什么有人会在enum 声明中使用它呢?

【问题讨论】:

  • @GrantWinney(不是我的近距离投票)但我明白它是如何“基于意见”的,因为问题本质上是“为什么有人在 0x04 更易读时使用 1 &lt;&lt; 2我”。
  • 我从来没有说过 0x04 更具可读性,我也没有比较两者。该问题的目的是了解此语句的副作用(= 能够组合标志)
  • Oscar,您的帖子没有任何问题(我认为这对于学习使用任何 C/C++/C#/Java/JavaScript 进行编码的人很有用)。但是不同的人阅读相同文本的方式不同——我只是用我的阅读方式来解释投票结束。
  • 我会小心在位移前加一个前导零 - 如果没有 89 那么文字不会被解释为八进制吗?这可能需要一两个小时的调试时间。
  • 如果你知道 C: 阅读 - What is the meaning of this declaration?

标签: c# enums operators


【解决方案1】:

这允许你做这样的事情:

var myEnumValue = MyEnum.open | MyEnum.close;

无需计算 2 的倍数的位值。

(像这样):

public enum MyEnum
{
    open     = 1,
    close    = 2,
    Maybe    = 4,
    ........
}

【讨论】:

  • 什么替代解决方案可以提供超过 64 个正交状态?
  • @GrijeshChauhan 大多数平台?这是 C#,因此整数类型的大小不依赖于平台。 &lt;&lt; 运算符的左操作数的类型决定了使用哪个重载。例如,s 是整数,1 &lt;&lt; s 给出 32 位 int1u &lt;&lt; s 给出 32 位无符号 uint1L &lt;&lt; s 给出 64 位 long1ul &lt;&lt; s 是 @ 987654338@, 和(BigInteger)1 &lt;&lt; sBigInteger.One &lt;&lt; s 给出一个任意大小的整数(需要参考System.Numerics.dll 程序集)。
  • @JeppeStigNielsen 知道了!...我不是来自c# 背景我觉得我应该分享答案,因为我知道这一点。 ...顺便说一句,如果在 c#sizeof(enum) > sizeof(one byte) 中,我不喜欢 c#,因为没有人喜欢在他的代码中使用 2^sizeof(int) 符号常量。
  • @GrijeshChauhan 在 C# 中,您可以像这样创建一个 8 位枚举类型:public enum Color : byte { Red, Yellow, Green, Blue, }
【解决方案2】:

这通常与位域一起使用,因为它很清楚模式是什么,消除了手动计算正确值的需要,从而减少了出错的机会

[Flags]
public enum SomeBitField
{
    open = 1 << 0    //1
    closed = 1 << 1  //2
    maybe = 1 << 2   //4
    other = 1 << 3   //8
    ...
}

【讨论】:

  • 我认为您的意思是按位运算,而不是位域。位域,至少在 C 世界中,是子字节结构成员。
【解决方案3】:

为了避免手动输入 Flags 枚举的值。

public enum MyEnum
{
    open     = 0x01,
    close    = 0x02,
    Maybe    = 0x04,
    ........
}

【讨论】:

  • +1。人们可能会在这样的enum 上加上[Flags] 以澄清用法……但并不是每个人都关心。
【解决方案4】:

这是为了制作一个可以组合的枚举。

它的实际含义是:

public enum MyEnum
{
    open = 1;
    close = 2;
    Maybe = 4;
    //...
}

这只是创建[Flags] 枚举的一种更安全的方法。

【讨论】:

    【解决方案5】:

    这只是一种更简洁/更直观的方式来编写这些位。 1、2、3 是比 0x1、0x2、0x4 等更易于人类阅读的序列。

    【讨论】:

      【解决方案6】:

      这里有很多答案描述了这个机制允许你做什么,但不是为什么 你会想要使用它。原因如下。

      短版:

      这种符号有助于与其他组件交互和通信 与其他工程师一起,因为它明确地告诉您单词中的位是什么 设置或清除,而不是在数值中隐藏该信息。

      所以我可以打电话给你说“嘿,打开 文件?”你会说,“位 0”。我会在我的代码中写 open = 1 &lt;&lt; 0。 因为&lt;&lt;右边的数字告诉你位数。

      .

      加长版:

      传统上,单词中的位从零开始从右到左编号。 所以最低有效位是第 0 位,当你走向 最重要的位。有几个benefits 来标记位 方式。

      一个好处是,无论字长如何,您都可以谈论相同的内容。 例如,我可以说在 32 位字 0x384A 和 8 位字 0x63 中,位 设置了 6 和 1。如果你在另一个方向编号你的位,你不能 这样做。

      另一个好处是位的值只是 2 的位次方 位置。例如,二进制 0101 设置了位 2 和 0。位 2 贡献 值4 (2^2) 给数字,位0 贡献值1 (2^0)。所以 number 的值当然是 4 + 1 = 5。

      冗长的背景解释让我们明白了这一点:&lt;&lt; 符号只需查看即可告诉您位数。

      语句1 &lt;&lt; n 中的数字 1 只是一个设置在 位位置 0。当您将该数字向左移动时,您将移动该集合 位到数字中的不同位置。方便地,您转移的金额 告诉你将要设置的位数。

      1 << 5:   This means bit 5.   The value is 0x20.
      1 << 12:  This means bit 12.  The value is 0x40000.
      1 << 17:  This means bit 17.  The value is 0x1000000.
      1 << 54:  This means bit 54.  The value is 0x40000000000000.
                (You can probably see that this notation might be helpful if
                you're defining bits in a 64-bit number)
      

      当您与他人互动时,这种表示法真的会派上用场 组件,例如将字中的位映射到硬件寄存器。就像你可能 有一个设备在您写入位 7 时打开。所以硬件工程师 会写一个数据表,说明第 7 位启用该设备。你会写 你的代码ENABLE = 1 &lt;&lt; 7。就这么简单。

      哦,开枪。工程师刚刚向数据表发送了一个勘误表,说它是 应该是第 15 位,而不是第 7 位。没关系,只需将代码更改为 ENABLE = 1 &lt;&lt; 15.

      如果ENABLE 实际上是同时设置了第 7 位和第 1 位怎么办?

      ENABLE = (1 &lt;&lt; 7) | (1 &lt;&lt; 1).

      一开始它可能看起来很奇怪和迟钝,但你会习惯的。你会 如果您明确需要知道某事物的位数,将不胜感激。

      【讨论】:

        【解决方案7】:

        等于二的幂。

        public enum SomeEnum
        {
            Enum1 = 1 << 0,    //1
            Enum2 = 1 << 1,    //2
            Enum3 = 1 << 2,    //4
            Enum4 = 1 << 3     //8
        }
        

        有了这样的枚举,你将拥有如下所示的函数:

        void foo(unsigned ind flags)
        {
            for (int = 0; i < MAX_NUMS; i++)
                if (1 << i & flags)
                {
                    //do some stuff...
                    //parameter to that stuff probably is i either enum value
                }
        }
        

        调用该函数将是foo(Enum2 | Enum3);,它将对所有给定的枚举值执行一些操作。

        【讨论】:

          猜你喜欢
          • 2017-11-14
          • 1970-01-01
          • 1970-01-01
          • 2013-07-22
          • 1970-01-01
          • 1970-01-01
          • 2010-10-01
          • 1970-01-01
          • 2022-11-28
          相关资源
          最近更新 更多