【问题标题】:What happens if we declare [Flags] enum in order?如果我们按顺序声明 [Flags] 枚举会发生什么?
【发布时间】:2014-03-31 06:47:12
【问题描述】:

我遇到过这个问题:What does the [Flags] Enum Attribute mean in C#?

我一直想知道的一件事是,使用公认的answer's example,如果我声明会发生什么:

[Flags]
public enum MyColors
{
    Yellow = 1,
    Green = 2,
    Red = 3,
    Blue = 4
}

该示例中的以下步骤会导致错误吗?如果没有,我怎样才能到达 MyColors.Red?

【问题讨论】:

  • 题外话:你期望MyColors.Yellow | MyColors.Blue返回MyColors.Green吗?如果是这样,如果你做对了,你也许可以做到这一点。

标签: c# enum-flags


【解决方案1】:

Flags 属性实际上并没有对枚举本身做任何事情,也不会影响它在代码中的使用方式。 Flags 属性确实影响的唯一一件事是 ToString 方法的输出。 Flags 属性的另一个目的是向开发人员指示他们应该如何使用枚举。您的示例不会导致任何错误;这只是愚蠢的代码。规则很简单:

  1. 如果一次只应使用一个值,则不要应用 Flags 属性并为该类型使用单数名称。
  2. 如果多个值可以一起使用,则应用 Flags 属性,对值使用 2 的幂,并为类型使用复数名称。

【讨论】:

  • 2 的幂。重要的区别。
【解决方案2】:

要详细说明 jdphenix 的答案,请记住 [Flags] 属性实际上并没有任何魔力。它只是在枚举上添加了一个纯粹的装饰标记,允许其他函数(默认情况下,只有枚举的 ToString 实现)将枚举视为标志枚举。

不管属性如何,枚举仍然只是一个数字,默认情况下是一个 Int32,周围有一些语法糖。所以如果你像以前那样定义你的枚举,那么做

MyColors newColor = MyColors.Yellow | MyColors.Green 

只会对 1 和 2 进行按位或运算。按位枚举的魔力不在属性中,但事实上 2 的幂允许您“打开”和关闭某个位。使用序数将关闭作为多个枚举值的二进制表示的一部分的位,从而使按位运算的结果毫无意义。

【讨论】:

    【解决方案3】:

    这会导致意想不到的结果。实现唯一性的常见做法是用 2 的幂来标记枚举值。

    例如Yellow 按位或Green 将导致Red 等等。

    MyColors colors = MyColors.Yellow | MyColors.Green;
    if (colors == MyColors.Red)
    {
        Console.WriteLine("Oops!")
    }
    

    还要注意Flags 属性在这里什么都不做,它给人的印象是你可以使用按位或

    【讨论】:

    • 除非,当然,预期的结果是唯一地命名每个组合:)(对于问题中的示例无效,但按递增顺序列出它们不是错误根据定义.)
    【解决方案4】:

    它不会按预期运行。对于每个枚举常量的声明值,您必须使用 2 的幂。这是直接来自您链接的答案的示例:

    [Flags]
    public enum MyColors
    {
        Yellow = 1,
        Green = 2,
        Red = 4,
        Blue = 8
    }
    

    如果声明的值不是 2 的幂:

    • 您将无法执行有意义的按位运算。
    • 您可以将它用于普通枚举(不会出现编译器错误)。

    【讨论】:

      【解决方案5】:

      所有 [Flags] 属性的作用就是允许您将按位运算符应用于枚举。

      [编辑是正确的 - 如果你不指定 [Flags] 甚至没有警告 - 我可以发誓它曾经是这样的......]

      您拥有的 =3(红色)非常有用,因为您可以定义组合以检查...在您的示例中:

      [Flags]
      public enum MyColors
      {
          Yellow = 1,
          Green = 2,
          YellowAndGreen = 3,
          Blue = 4
      }
      

      现在,显然这是一个愚蠢的例子,但请考虑以下内容:

      [Flags]
      public enum MyStuff
      {
          HasCar = 1,
          HasDog = 2,
          HasKids = 4,
          HasEverything = 7,
      }
      

      现在,要检查变量是否包含所有内容,您可以执行以下操作:

      return (myStuff & MyStuff.HasEverything) == MyStuff.HasEverything;
      

      【讨论】:

      • All the [Flags] attribute does is allow you to apply bitwise operators to the enum - 甚至没有那么多。
      • 我同意@Rawling,这只是一个提示,并提供了一个更漂亮的ToString
      • 当然最后一个例子也是“愚蠢的”,因为包含 HasCar 和 HasDog 将意味着 HasKids (1 | 2 = 3)。同样,2 的幂
      • @LasseV.Karlsen:哈哈。不敢相信我犯了这么愚蠢的错误。谢谢。固定。
      猜你喜欢
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      相关资源
      最近更新 更多