1545

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?

Selim Yildiz
  • 4,224
  • 6
  • 14
  • 25
Brian Leahy
  • 32,433
  • 10
  • 42
  • 60
  • It's also worth noting, in addition to the accepted answer, that VB.NET actually _requires_ [Flags] - at least according to the .NET guys: http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/51e5f20b-7da4-4dd2-ab44-2ddb5802fa88/ – Rushyo Jul 30 '12 at 15:38
  • 9
    Note, not required in VB these days. Save behaviour as C# - just changes the ToString() output. Note, you can also do logical OR, WITHIN the Enum itself. Very cool. Cat = 1, Dog = 2, CatAndDog = Cat || Dog. – Chalky Aug 04 '15 at 09:13
  • 14
    @Chalky You mean `CatAndDog = Cat | Dog` (the logical OR instead of the Conditional), I assume? – DdW Sep 12 '16 at 12:20
  • 7
    @DdW, partially correct: | should be used, but | is called the binary OR. II is the logical OR (that allows short-circuiting): At least according to Microsoft ;) https://msdn.microsoft.com/en-us/library/f355wky8.aspx – Pieter21 Apr 01 '18 at 06:08

13 Answers13

2268

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:

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:

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. 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:

[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.

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:

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. Under the covers, your enumeration values look like this in binary ones and zeros:

 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 | operator, AllowedColors looks like this:

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

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

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

Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. 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.

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

Matt Jenkins
  • 2,507
  • 1
  • 24
  • 32
andynil
  • 25,900
  • 2
  • 27
  • 26
  • Also, I don't get what the Flags attribute really does? I seem to be able to define and use my flags enum just fine without the attribute. Is it merely used as indication that the enum can be used as flags? – Oskar Aug 06 '09 at 09:11
  • 163
    Flags itself does nothing. Also, C# does not require Flags per se. But the `ToString` implementation of your enum uses Flags, and so does `Enum.IsDefined`, `Enum.Parse`, etc. Try to remove Flags and look at the result of MyColor.Yellow | MyColor.Red; without it you get "5", with Flags you get "Yellow, Red". Some other parts of the framework also use [Flags] (e.g., XML Serialization). – Ruben Aug 17 '09 at 17:30
  • The Flags attribute has more of an effect than the ToString method. Visual studio uses it at least to some degree when using an Enum in the designer. See my question here: http://stackoverflow.com/q/15663166/1111886 – Fr33dan Mar 27 '13 at 15:50
  • 54
    I prefer to use constants of the form A = 1 << 0, B = 1 << 1, C = 1 << 2 ... Much easier to read, understand, visually check and change. – Nick Westgate Apr 09 '13 at 12:06
  • .HasFlag(Enum flag) method takes parameter of Enum type, so the value type should be boxed which is bad for performance – Aleksei Chepovoi May 04 '13 at 12:59
  • @AlekseiChepovoi Enum derives from the `ValueType` class, this means that it is treated as a `struct` the same way as `int`, `float`, etc. – borrrden Jun 24 '13 at 06:46
  • @borrrden, when we pass Enum class (class that defines HasFlag method), it is passed by reference, as I got it. I've read this in Jeffrey Richter's CLR via C# third edition, Enums and Bit Flags chapter. – Aleksei Chepovoi Jun 26 '13 at 20:45
  • @AlekseiChepovoi I also have that book, so I will check it. It seems to fly in the face of everything I know about C# though. Every article I can find says that enums are value objects that are not allocated on the heap. – borrrden Jun 27 '13 at 01:35
  • 2
    @borrrden, hell yeahh! I found this: http://msdn.microsoft.com/en-us/library/system.enum.aspx - see "Remarks" part: "Enum is the base class for all enumerations in the .NET Framework." and "The enumeration does not explicitly inherit from Enum; the inheritance relationship is handled implicitly by the compiler." So, when you write: public enum bla bla bla - this is a value type. But, the HasFlag method wants you to give him an instance of System.Enum which is a class (reference type:) – Aleksei Chepovoi Jun 28 '13 at 14:59
  • 1
    Enum.IsDefined does not take the FlagsAttribute into account. None of the following return true, even with the attribute: Yellow | Green, "Yellow, Green", 3 – TheXenocide Dec 06 '13 at 21:29
  • your example would make more sense from a Flag perceptive if blue = 2 and green = 3 as after all green is the combination of yellow and blue – MikeT Jun 11 '15 at 09:14
  • 3
    If you want to exclude a flag from the enumeration, use xor, which is ^ in C#. So if you have `myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;`. You can do: `myProperties.AllowedColors = myProperties.AllowedColors ^ MyColor.Blue //myProperties.AllowedColors == MyColor.Red | Mycolor.Green` – Josh Noe Feb 09 '18 at 22:20
  • I was looking what 10 represents... after some testing this corresponds to value 2 and value 8 or `Green | Blue`. also the values of `Yellow = 1, Green = 2,... 8` helps to easily understand what a 9 (8+1) or 11 (8+2+1) means vs the shift representation (< – Jaider May 25 '21 at 23:58
810

You can also do this

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

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

Orion Edwards
  • 113,829
  • 60
  • 223
  • 307
  • The only thing I don't like about these shortcuts is if you happen to save these enums in the database as ints. Then you have to get the calculator out a lot more than once to figure out what values correspond to which enum when analyzing data. – JeremyWeir May 14 '12 at 06:15
  • 1
    @JeremyWeir Can you explain how that would be different from using `1, 2 , 4, 8, 16, ...`? Also the calculator of Windows 7 has bits which you can click on. – Silvermind May 27 '12 at 08:03
  • 22
    That's what I mean, I prefer to have the full int in source code. If I have a column on a table in the database called MyEnum that stores a value of one of the enums, and a record has 131,072, I would need to get out my calculator to figure out that that corresponds to the enum with the value 1<<17. As opposed to just seeing the value 131,072 written in the source. – JeremyWeir May 29 '12 at 17:11
  • 6
    "it's all done at compile time" this type of comment may be interesting to some, but I find it frustrating because it implies that say, 20 bit-shifts at run-time will have any measurable impact on performance. CPUs are very good at bit-shifts, enums are not going to have an arbitrary number of members, and this won't work for more than 32 or 64 elements anyway. Not remotely important as a performance issue. – jwg Feb 14 '13 at 09:48
  • 7
    @jwg I agree, it's silly to be overly worried about the runtime performance of this, but all the same, I do think its nice to know that this isn't going to be inserting bitshifts anywhere you use the enum. More of a 'that's neat' thing rather than anything related to performance – Orion Edwards Feb 15 '13 at 19:25
  • 20
    @JeremyWeir - Several bits are going to be set in a flag enumeration value. So your method of data analysis is what is improper. Run a procedure to Represent your integer value in binary. 131,072 [D] = 0000 0000 0000 0001 0000 0000 0000 0000 [B] [32].. With the 17th bit set, an enum value assigned 1<<17 is easily determinable. 0110 0011 0011 0101 0101 0011 0101 1011 [b] [32] .. the enum values assign 1<<31, 1<<30, 1<<26, 1<<25.. etc. etc. is determinable without even the aid of a calculator at all.. which I doubt you would be able to determine at all without getting the binary rep. – Brett Caswell Mar 19 '13 at 05:41
  • 15
    Also pointing out you can bit-shift from "previous" enum values rather than directly from numbers, i.e. `Third = Second << 1` rather than `Third = 1 << 2` -- see [more complete description below](http://stackoverflow.com/a/16591032/1037948) – drzaus May 16 '13 at 15:05
  • 31
    I like this, but once you get to the upper limits of the underlying enum type, the compiler doesn't warn against bit shifts such as `1 << 31 == -2147483648`, `1 << 32 == 1`, `1 << 33 == 2`, and so on. By contrast, if you say `ThirtySecond = 2147483648` for an int type enum, the compiler throws an error. – aaaantoine Jun 03 '14 at 20:58
  • 6
    Just to add another option that's new with C# 7, you can use `0b1`, `0b10` etc. (or `0b00000001` if you like everything lining up properly!) – Graham Wager Mar 15 '17 at 17:43
122

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:

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,   // 1
    Two     = 1 << 1,   // 2
    Three   = 1 << 2,   // 4
    Four    = 1 << 3,   // 8

    // combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

You can declare

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,       // 1
    // now that value 1 is available, start shifting from there
    Two     = One << 1,     // 2
    Three   = Two << 1,     // 4
    Four    = Three << 1,   // 8

    // same combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

Confirming with LinqPad:

foreach(var e in Enum.GetValues(typeof(Options))) {
    string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}

Results in:

None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
Community
  • 1
  • 1
drzaus
  • 21,536
  • 14
  • 123
  • 183
  • 27
    The combinations are a good recommendation, but I think the chained bit-shift would be prone to copy-and-paste errors such as Two = One << 1, Three = One << 1, etc... The incrementing integers of the form 1 << n are safer and the intent is clearer. – Rupert Rawnsley Mar 20 '14 at 13:00
  • 2
    @RupertRawnsley to quote my answer: > Not necessarily recommending it, but just pointing out you can – drzaus Mar 20 '14 at 16:13
49

Please see the following for an example which shows the declaration and potential usage:

namespace Flags
{
    class Program
    {
        [Flags]
        public enum MyFlags : short
        {
            Foo = 0x1,
            Bar = 0x2,
            Baz = 0x4
        }

        static void Main(string[] args)
        {
            MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;

            if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
            {
                Console.WriteLine("Item has Foo flag set");
            }
        }
    }
}
Jaider
  • 12,387
  • 5
  • 59
  • 77
OJ.
  • 27,508
  • 5
  • 52
  • 69
  • 2
    This example works even if you leave out [Flags]. It's the [Flags] part I'm trying to learn about. – gbarry Aug 06 '19 at 23:21
46

In extension to the accepted answer, in C#7 the enum flags can be written using binary literals:

[Flags]
public enum MyColors
{
    None   = 0b0000,
    Yellow = 0b0001,
    Green  = 0b0010,
    Red    = 0b0100,
    Blue   = 0b1000
}

I think this representation makes it clear how the flags work under the covers.

Thorkil Holm-Jacobsen
  • 6,190
  • 3
  • 25
  • 40
  • 8
    And in C# 7.2 it's even clearer with [leading separator](https://docs.microsoft.com/it-it/dotnet/csharp/language-reference/proposals/csharp-7.2/leading-separator)! `0b_0100` – Vincenzo Petronio Oct 26 '19 at 08:51
40

I asked recently about something similar.

If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)

This allows you to do:

[Flags]
public enum PossibleOptions : byte
{
    None = 0,
    OptionOne = 1,
    OptionTwo = 2,
    OptionThree = 4,
    OptionFour = 8,

    //combinations can be in the enum too
    OptionOneAndTwo = OptionOne | OptionTwo,
    OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
    ...
}

Then you can do:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

if( opt.IsSet( PossibleOptions.OptionOne ) ) {
    //optionOne is one of those set
}

I find this easier to read than the most ways of checking the included flags.

Community
  • 1
  • 1
Keith
  • 133,927
  • 68
  • 273
  • 391
  • IsSet is an extension method I assume? – Robert MacLean Jun 02 '09 at 10:09
  • Yeah - read the other question that I link to for details: http://stackoverflow.com/questions/7244 – Keith Jun 02 '09 at 12:16
  • 72
    .NET 4 adds a `HasFlag` method to enumerations, so you can do `opt.HasFlag( PossibleOptions.OptionOne )` without having to write your own extensions – Orion Edwards Jul 19 '10 at 20:53
  • 1
    Note that `HasFlag` is [much slower](https://stackoverflow.com/q/7368652/1364007) than doing bitwise operations. – Wai Ha Lee Sep 12 '18 at 15:45
  • 1
    @WaiHaLee You can use CodeJam.EnumHelper.IsFlagSet extension method which is compiled to a fast version using Expression: https://github.com/rsdn/CodeJam/wiki/M_CodeJam_EnumHelper_IsFlagSet__1 – NN_ Apr 29 '19 at 20:09
28

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.

[Flags] 
enum SuitsFlags { 

    None =     0,

    Spades =   1 << 0, 
    Clubs =    1 << 1, 
    Diamonds = 1 << 2, 
    Hearts =   1 << 3,

    All =      ~(~0 << 4)

}

Usage:

Spades | Clubs | Diamonds | Hearts == All  // true
Spades & Clubs == None  // true

 
Update 2019-10:

Since C# 7.0 you can use binary literals, which are probably more intuitive to read:

[Flags] 
enum SuitsFlags { 

    None =     0b0000,

    Spades =   0b0001, 
    Clubs =    0b0010, 
    Diamonds = 0b0100, 
    Hearts =   0b1000,

    All =      0b1111

}
Jpsy
  • 17,245
  • 6
  • 99
  • 99
23

@Nidonocu

To add another flag to an existing set of values, use the OR assignment operator.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));
steve_c
  • 5,933
  • 4
  • 28
  • 40
18

To add Mode.Write:

Mode = Mode | Mode.Write;
shA.t
  • 15,232
  • 5
  • 47
  • 95
David Wengier
  • 9,655
  • 5
  • 35
  • 43
15

There's something overly verbose to me about the if ((x & y) == y)... construct, especially if x AND y 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.

[1] See Jaime's comment. If we were authentically bitmasking, we'd only need to check that the result was positive. But since enums can be negative, even, strangely, when combined with the [Flags] attribute, it's defensive to code for != 0 rather than > 0.

Building off of @andnil's setup...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BitFlagPlay
{
    class Program
    {
        [Flags]
        public enum MyColor
        {
            Yellow = 0x01,
            Green = 0x02,
            Red = 0x04,
            Blue = 0x08
        }

        static void Main(string[] args)
        {
            var myColor = MyColor.Yellow | MyColor.Blue;
            var acceptableColors = MyColor.Yellow | MyColor.Red;

            Console.WriteLine((myColor & MyColor.Blue) != 0);     // True
            Console.WriteLine((myColor & MyColor.Red) != 0);      // False                
            Console.WriteLine((myColor & acceptableColors) != 0); // True
            // ... though only Yellow is shared.

            Console.WriteLine((myColor & MyColor.Green) != 0);    // Wait a minute... ;^D

            Console.Read();
        }
    }
}
ruffin
  • 13,513
  • 8
  • 72
  • 118
  • Enum may be based on a signed type, so you should use "!= 0" instead of ">0". – raven Aug 16 '13 at 09:18
  • @JaimePardos -- As long as we keep them honest bytes, as I do in this example, there's no concept of negative. Just 0 to 255. As [MSDN warns](http://msdn.microsoft.com/en-us/library/system.enum.aspx), "Use caution if you define a negative number as a flag enumerated constant because... [that] might make your code confusing and encourage coding errors." It's strange to think in terms of "negative bitflags"! ;^) I'll edit more in a bit. But you're right, if we do use negative values in our `enum`, we'd need to check for `!= 0`. – ruffin Aug 16 '13 at 13:23
11

Flags allow you to use bitmasking inside your enumeration. This allows you to combine enumeration values, while retaining which ones are specified.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}
Markus Safar
  • 5,899
  • 5
  • 25
  • 41
Jay Mooney
  • 2,020
  • 1
  • 18
  • 22
1

Apologies if someone already noticed this scenario. A perfect example of flags we can see in reflection. Yes Binding Flags ENUM.

[System.Flags]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public enum BindingFlags

Usage

// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof (TestClass);

Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public | 
    BindingFlags.Static, null, null, new object [] {});
bad_coder
  • 5,829
  • 13
  • 26
  • 41
kbvishnu
  • 12,180
  • 17
  • 64
  • 97
-3
  • Flags are used when an enumerable value represents a collection of enum members.

  • here we use bitwise operators, | and &

  • Example

                 [Flags]
                 public enum Sides { Left=0, Right=1, Top=2, Bottom=3 }
    
                 Sides leftRight = Sides.Left | Sides.Right;
                 Console.WriteLine (leftRight);//Left, Right
    
                 string stringValue = leftRight.ToString();
                 Console.WriteLine (stringValue);//Left, Right
    
                 Sides s = Sides.Left;
                 s |= Sides.Right;
                 Console.WriteLine (s);//Left, Right
    
                 s ^= Sides.Right; // Toggles Sides.Right
                 Console.WriteLine (s); //Left
    
  • 2
    Your example is wrong (and does not produce the output it claims) because the proper use of `Flags` requires that your enum values have unique bits set. And there should be at least **one** set (unless you a pseudo value like `None`). Your enum should like ` public enum Sides { Left=1, Right=2, Top=4, Bottom=8 } ` – Jakob Nov 18 '20 at 13:29