[Flags]枚举属性在C#中是什么意思?

问题描述 投票:1362回答:11

[我不时看到如下枚举:

[Flags]
public enum Options 
{
    None    = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    Option4 = 8
}

我不知道[Flags]属性的确切用途。

任何人都可以发表很好的解释或榜样?

c# enums flags
11个回答
2055
投票

[Flags]属性应在可枚举表示可能值而不是单个值的集合时使用。此类集合通常与按位运算符一起使用,例如:

var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

请注意,[Flags]属性没有本身就启用了它-它所做的只是允许.ToString()方法很好地表示:

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }

...

var str1 = (Suits.Spades | Suits.Diamonds).ToString();
           // "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
           // "Spades, Diamonds"

同样重要的是要注意,[Flags] 不是自动使枚举值的幂为2。如果省略数字值,则枚举将无法按位操作,因为默认情况下,该值从0开始并递增。

不正确的声明:

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

如果以这种方式声明,则值将为黄色= 0,绿色= 1,红色= 2,蓝色=3。这将使它无用作为标志。

这是正确声明的示例:

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

要检索属性中的不同值,可以执行以下操作:

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
    // Yellow is allowed...
}

或.NET 4之前:

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
    // Yellow is allowed...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
    // Green is allowed...
}    

在幕后

之所以有效,是因为您在枚举中使用了2的幂。在幕后,您的枚举值看起来像这样的二进制1和0:

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

类似地,使用二进制按位或|运算符将属性AllowedColors设置为红色,绿色和蓝色后,AllowedColors看起来像这样:

myProperties.AllowedColors: 00001110

因此,当您检索该值时,您实际上是在对这些值执行按位与&

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

无= 0值

关于在枚举中使用0,引自MSDN:

[Flags]
public enum MyColors
{
    None = 0,
    ....
}

使用None作为值为零的标志枚举常量的名称。 您不能在按位与运算中使用无枚举常量来测试标志,因为结果始终为零。但是,您可以对数值与无枚举常量进行逻辑比较,而不是按位比较确定是否设置了数值中的任何位。

您可以在msdndesigning flags at msdn中找到有关flags属性及其用法的更多信息,>


12
投票
使用标志时,我经常声明其他无和所有项目。这些有助于检查是否设置了所有标志或没有设置标志。

10
投票
标记允许您在枚举中使用位掩码。这使您可以合并枚举值,同时保留指定的值。

755
投票

您也可以这样做


109
投票

合并答案https://stackoverflow.com/a/8462/1037948(通过位移进行声明)和https://stackoverflow.com/a/9117/1037948(使用声明进行组合),您可以将先前的值进行位移而不是使用数字。不一定推荐它,而只是指出您可以。


48
投票

请参见以下示例,其中显示了声明和潜在用法:


35
投票

asked recently关于类似的内容。


30
投票

在接受的答案的扩展中,在C#7中,可以使用二进制文字编写枚举标志:


22
投票

@ Nidonocu


17
投票

添加Mode.Write


13
投票

if ((x & y) == y)...构造对我来说过于冗长,特别是如果xy都是复合标志集,而您只想知道是否存在[[any

© www.soinside.com 2019 - 2024. All rights reserved.