Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
482 views
in Technique[技术] by (71.8m points)

c# - C#中的[Flags]枚举属性是什么意思?(What does the [Flags] Enum Attribute mean in C#?)

From time to time I see an enum like the following:

(我不时看到如下枚举:)

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

I don't understand what exactly the [Flags] -attribute does.

(我不明白[Flags]属性的确切作用。)

Anyone have a good explanation or example they could post?

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

  ask by Brian Leahy translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value.

(每当枚举表示可能值的集合而不是单个值时,应使用[Flags]属性。)

Such collections are often used with bitwise operators, for example:

(此类集合通常与按位运算符一起使用,例如:)

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

Note that the [Flags] attribute doesn't enable this by itself - all it does is allow a nice representation by the .ToString() method:

(请注意, [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"

It is also important to note that [Flags] does not automatically make the enum values powers of two.

(同样重要的是要注意[Flags] 不会自动使枚举值的幂为2。)

If you omit the numeric values, the enum will not work as one might expect in bitwise operations, because by default the values start with 0 and increment.

(如果省略数字值,则枚举将无法按位操作,因为默认情况下,该值从0开始并递增。)

Incorrect declaration:

(不正确的声明:)

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

The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless as flags.

(如果以此方式声明,则这些值将为Yellow = 0,Green = 1,Red = 2,Blue =3。这将使其变为无用的标志。)

Here's an example of a correct declaration:

(这是正确声明的示例:)

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

To retrieve the distinct values in your property, one can do this:

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

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

or prior to .NET 4:

(或.NET 4之前的版本:)

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

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

Under the covers

(掩护下)

This works because you used powers of two in your enumeration.

(之所以可行,是因为您在枚举中使用了2的幂。)

Under the covers, your enumeration values look like this in binary ones and zeros:

(在幕后,您的枚举值看起来像这样的二进制1和0:)

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

Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR |

(同样,在使用二进制按位OR |将属性AllowedColors设置为Red,Green和Blue之后|)

operator, AllowedColors looks like this:

(运算符, AllowedColors看起来像这样:)

myProperties.AllowedColors: 00001110

So when you retrieve the value you are actually performing bitwise AND & on the values:

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

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

The None = 0 value

(无= 0值)

And regarding the use of 0 in your enumeration, quoting from MSDN:

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

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

Use None as the name of the flag enumerated constant whose value is zero.

(使用None作为值为零的标志枚举常量的名称。)

You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero.

(您不能在按位与运算中使用None枚举常量来测试标志,因为结果始终为零。)

However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.

(但是,您可以在数值和None枚举常量之间进行逻辑比较而不是按位比较,以确定是否设置了数值中的任何位。)

You can find more info about the flags attribute and its usage at msdn and designing flags at msdn

(您可以在msdn上找到有关flags属性及其用法以及在msdn上 设计标志的更多信息)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...