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.
Anyone have a good explanation or example they could post?
When working with flags I often declare additional None and All items. These are helpful to check whether all flags are set or no flag is set.
Usage:
Update 2019-10:
Since C# 7.0 you can use binary literals, which are probably more intuitive to read:
To add
Mode.Write
:The
[Flags]
attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value. Such collections are often used with bitwise operators, for example:Note that the
[Flags]
attribute doesn't enable this by itself - all it does is allow a nice representation by the.ToString()
method:It is also important to note that
[Flags]
does not automatically make the enum values powers of two. 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.Incorrect declaration:
The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless as flags.
Here's an example of a correct declaration:
To retrieve the distinct values in your property, one can do this:
or prior to .NET 4:
Under the covers
This works because you used powers of two in your enumeration. Under the covers, your enumeration values look like this in binary ones and zeros:
Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR
|
operator, AllowedColors looks like this:So when you retrieve the value you are actually performing bitwise AND
&
on the values:The None = 0 value
And regarding the use of
0
in your enumeration, quoting from MSDN:You can find more info about the flags attribute and its usage at msdn and designing flags at msdn
There's something overly verbose to me about the
if ((x & y) == y)...
construct, especially ifx
ANDy
are both compound sets of flags and you only want to know if there's any overlap.In this case, all you really need to know is if there's a non-zero value[1] after you've bitmasked.
Building off of @andnil's setup...
You can also do this
I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time
Combining answers https://stackoverflow.com/a/8462/1037948 (declaration via bit-shifting) and https://stackoverflow.com/a/9117/1037948 (using combinations in declaration) you can bit-shift previous values rather than using numbers. Not necessarily recommending it, but just pointing out you can.
Rather than:
You can declare
Confirming with LinqPad:
Results in: