Enum values as bit flags - using FlagsAttribute

The other day, I was using the RegexOptions enum when creating a Regular Expression, and I thought it would be useful to dedicate a blog entry to using enumeration values as flags.

The following is a poor example, but it should be illustrative enough.

Imagine we have a Client class, and one of the Client properties is ClientState. The ClientState enum can be defined as follows:

public enum ClientStates
{
  Ordinary,
  HasDiscount,
  IsSupplier,
  IsBlackListed,
  IsOverdrawn
}

As you can see - these options could be combined in several ways. Rather then creating separate properties in the Client class, we could enable a bitwise combination of enumeration values by using the FlagsAttribute, when defining our enum type. See below.

[Flags]
public enum ClientStates
{
  Ordinary,
  HasDiscount,
  IsSupplier,
  IsBlackListed,
  IsOverdrawn
}


This means we can now use the bitwise OR operator to combine these enum values. For instance:

Client c = new Client();
c.ClientState = (ClientStates.HasDiscount|ClientStates.IsSupplier|ClientStates.IsOverdrawn);

By setting the FlagsAttribute, the values for each enum value now effectively become bitflag patterns that look as follows if you see them in binary form:

00000000  0
00000001  1
00000010  2
00000100  4
00001000  16
00010000  32
00100000  64
01000000  128


As you can see, this bit pattern in our enum values enables us to use the bitwise operator and combine enum values. It is plain to see that all enum values combined, using the bitwise OR, would result in
11111111.

So, how do we check what particular ClientState values have been set? The key is the bitwise AND operator. Let's take our existing Client object 'c'.

[Flags]
public enum ClientStates
{
  Ordinary,       // 0000
  HasDiscount,    // 0001
  IsSupplier,     // 0010
  IsBlackListed,  // 0100
  IsOverdrawn     // 1000
}

So for instance, if we want to check c.ClientState for ClientStates.HasDiscount we can use the following expression:

(c.ClientState & ClientStates.HasDiscount) == ClientStates.HasDiscount

Assuming that c.ClientState contains HasDiscount, IsSupplier and IsOverdrawn, the bit patterns would look like:

c.ClientState:                1011
ClientStates.HasDiscount:     0001
(Logical AND):                0001


So by AND’ing the bit value to check for with the combined bit pattern, we either get the same enum bit pattern value back, or we get a bit pattern which only contains zero’s.

Here’s a little helper method you can use to check for particular ClientStates enum flag values:

public static bool ContainsClientState(ClientStates combined, ClientStates checkagainst)

{

  return ((combined & checkagainst)==checkagainst);
}


That’s it for now. Feel free to leave any comments. Cheers!

67 Comments

  • Enums will have values 0, 1, 2, 3, ... by default. AFAIK adding FlagsAttribute doesn't change this.

    I think you need to explicitly set the values you want, e.g.:

    Ordinary = 0,

    HasDiscount = 1,

    IsSupplier = 2,

    IsBlackListed = 4,

    IsOverdrawn = 8

  • You don't have to set them yourself, but they will still hold the decimal values 0,1,2,3,4,5 etc. (like normal enums, so not 0,1,2,4,8!).



    However, for the CLR to work with these bit patterns, internally some conversion is taking place. I never said the actual enum value is equal to bit pattern value, it just makes it easier to understand these enum bit flags.

  • But does this actually work without setting the values yourself? I've done a few tests and in my tests, it only works without setting the values if you stick with very small sets. Once I use an enum with 8 or so values, I have to set it myself or it no longer works.



    If you have an example of this with 8 or more flags that works, can you post it?

  • I wrote a proof-of-concept on this and it won't work unless you specify enum values (0,1,2,4,8,...). Well, technically it will work for three items in the enum since they get 0,1,2 ... but beyond that, they must be specified.

  • To be more specific, you must specify values for each element in your enum. For example:



    public enum Tools : int

    {

    None = 0 ,

    Hammer = 1,

    Screwdriver = 2,

    Pliers = 4,

    Wrench = 8

    }

  • You need to be careful of the first item as it is set to 0. This means that the conditional test in the sample :



    c.ClientState & ClientStates.HasDiscount) == ClientStates.HasDiscount



    will always equate to true. You need to start the enum with a dummy entry - unless someone has a better solution?



    This was particularly wierd as when debugging the if statement was never visited and I could not set the run point to it. The disassemled code showed the if line had been removed!



    Note, the above condition could also be written as:



    c.ClientState & ClientStates.HasDiscount) != 0



    though this has the reverse effect of alway equating to false.

  • Great article - exactly what I was looking for. Thanks very much




  • A very interesting site, thank you very much !
    [URL=http://tts23.50megs.com/index.html]index[/URL]
    [URL=http://hometown.aol.com/hlorazepamov/index.html]index[/URL]
    mevacor
    [url=http://hometown.aol.com/mevacors]mevacor[/url]
    albenza
    [url=http://hometown.aol.com/albenzas]albenza[/url]
    viramune
    [url=http://hometown.aol.com/viramunew]viramune[/url]
    sporanox
    [url=http://hometown.aol.com/sporanoxe]sporanox[/url]
    sumycin
    [url=http://hometown.aol.com/sumycins]sumycin[/url]
    aricept
    [url=http://4aricept.blogspot.com]aricept[/url]
    aceon
    [url=http://4aceon.blogspot.com]aceon[/url]
    albenza
    [url=http://4albenza.blogspot.com]albenza[/url]
    aldactone
    [url=http://4aldactone.blogspot.com]aldactone[/url]
    A very interesting site, thank you very much ! My Homepage :
    phentermine
    [url=http://4phentermine.blogspot.com]phentermine[/url]


  • So if I want to pass values around, am I passing the enum descriptors, the integers or the binary ox0100?

  • Great article. Found what I was searching for.

    The "And" usage was good.

    Thanks.

  • Thank you, this was very helpful. I'm doing:

    public enum CommitType {
    Insert = 1,
    Update = 2,
    Remove = 4 };

  • You gotta use 8 after 4 as enum values. So the line does not go on like 0,1,2,4,16,32, instead it must be 0,1,2,4,8,16,32.

  • How can i check if an enum contains other enum?

    example:
    [Flags]
    public enum MyEnum

    {
    None,
    First,
    Second,
    All = First | Second
    }
    .....
    public MyEnum one = MyEnum.First ;
    public MyEnum two = MyEnum.All;

    if(one is in two)//psaudo code
    {
    ...
    }

  • To enter bit values more easily, use the left shift operator, like this:

    [FlagsAttribute]
    public enum MyFlagsEnum
    {
    None = 0,
    One = 1 << 1,
    Two = 1 << 2,
    Three = 1 << 3,
    Four = 1 << 4
    }

  • @unknown programmer

    Technically you don't "gotta use 8", you can use any combination of numbers that are single bits. You could choose 1 & 256 if you like. But it does appear the original poster screwed up the binary -> decimal conversion.

    00000000 0
    00000001 1
    00000010 2
    00000100 4
    00001000 16 <-- 1000 = 8, rest of sequence is off
    00010000 32 by a factor of 2
    00100000 64
    01000000 128

    @original poster

    Using ClientState(s?) as a parameter/variable is a bad idea if you want to do the bitwise combinations which I think was the whole point of this article.

    ClientState state = IsSupplier | IsBlackListed;

    This makes an illegal enum in C/C++, and your compiler should complain! 0110 was not assigned a value in the enum.

    Storing into an int is legal.

    int state = IsSupplier | IsBlackListed;

    To make the other work, you have to add definitions to your enum. Which are not really something you want to do -- it would be tedious to map out all 255 combinations for an 8 bit enum.

    IsSupplier_AND_IsBlackListed = 0110
    or maybe
    DUMMY1 = 0110

  • ClientState state = IsSupplier | IsBlackListed;

    That IS a valid enum as long as you use the [Flags] attribute, which is the point of the article.

    Here's how I roll:

    [Flags]
    public enum Column
    {
    None = 0,
    Priority = 1 << 0,
    Customer = 1 << 1,
    Contract = 1 << 2,
    Description = 1 << 3,
    Tech = 1 << 4,
    Created = 1 << 5,
    Scheduled = 1 << 6,
    DueDate = 1 << 7,
    All = int.MaxValue
    };

    The [Flags] attribute allows you to do this:
    Column MyColumns = Column.Customer | Column.Contract;

    To check for a flag:
    if((MyColumns & Column.Customer) != 0)

    To set a flag:
    MyColumns |= Column.Tech;

    To clear a flag:
    MyColumns &= ~Column.Tech;

    To toggle (flip) a flag:
    MyColumns ^= Column.Contract;

    To clear all flags:
    MyColumns = Column.None;

    To set all flags:
    MyColumns = Column.All;

    To set all flags EXCEPT one or more:
    MyColumns = Column.All ^ Column.Tech ^ Column.Status;

  • This will not work, as [Flags] attribute is solely instructs ToString() of the enum to recognize combined values.
    You still need to set values manually to powers of 2 to use it like flags.

  • Since you know how to toggle (flip) a flag with:

    MyColumns ^= Column.Contract;

    Then, to clear all flags:

    MyColumns ^= MyColumns;

  • Another way to check for a flag:

    if((MyColumns & Column.Customer) == Column.Customer)

  • To shorten your statements you can use extensions like this:
    public static class EnumExtensions
    {
    public static bool Is(this object value, object value2)
    {
    return (Convert.ToInt32(value2) & Convert.ToInt32(value)) == Convert.ToInt32(value2);
    }
    }


    example:
    if (MyColumns.Is(Column.Customer)) ...

  • Best transparent bikini

  • This article is completely wrong. Maybe next time you could test what you say before wasting everyone's time and making yourself look like a fool in the process.

  • I like your work!,

  • Where it is possible to buy the,

  • So where it to find,

  • amazing stuff thanx :)

  • I think it's considered bad practice to use Flags-attribute when all values isn't concidered a valid state for an object.

    Take for example this:

    [Flags]
    public enum ObjectState {
    Unchanged,
    Changed,
    Deleted
    }

    It's not logical that an object can have all these state at any one time. This enum should be created without the Flags-attribute.

  • Nice post, thanks for writing!

  • aircraft accidents videos gup videos meningomyelocele video guy metzger utube.

  • gawad kalinga utube estoques video oscar video fast forward vidoe.

  • meryl video lehmann videos hockey enforcers video jessie mccartney video.

  • dein eigenes tuningvideo ginners video flatulent videos etard video.

  • j&r guarin video stephanie mcmahon video peter manfredo video adds videos.

  • At least a clear post on the 'Flags' atrribute.
    Danke cheune

  • thanks that was really helpful!

  • This article has so many flaws it should be either corrected (i.e. rewritten) or removed.

    As a few people have stated, if you use [Flags] with enums you should always specify the values in powers of 2 (1,2,4,8 etc) so the bitwise operations work correctly in all cases. You *can* skip values in the series (ie the series 1,2,8,16 is missing 4) but you cannot have duplicate values or values that aren't powers of 2.

    At any rate, [Flags] does nothing magical behind the scene. If you use [Flags] and don't follow the rules above, have fun chasing the bugs.

  • A very helpful article. I'm using enum flags to control access to various tabs in an admin interface.

    Thanks

    jamesakadamingo

  • It's great when you are just surfing the web and find something wonderful like this!

  • This blog appears to recieve a great deal of visitors. How do you promote it? It offers a nice unique twist on things. I guess having something authentic or substantial to talk about is the most important factor.

  • According to Correll, Monaghan was forced to rechristen the store as Domino’s when Dominick complained he was "besmirching his name" with a lousy product.
    Modern pizza originated in Italy as the Neapolitan pie with tomato.

  • Awesome post, really cool stuff! Like James I'm also using enum flags.

  • Great post thanks for the read!!

  • Nach meiner Meinung irren Sie sich. Geben Sie wir werden besprechen. Schreiben Sie mir in PM, wir werden umgehen.


  • Winning isn’t everything, it is the only thing. (Nothing matters but winning).

  • Interesting, didn't know C# had this capability. Kind of wish that was also in C++, just a handy little detail.

    Maybe once C++0x is out, the committee will look at some of the improvements made to C# for ideas.

  • This post will help me at my new project!

  • Nice It is new for me.
    Thanks

  • What a great post I'll use this next time I do anything with regex Thanks for the useful incite

  • Such a small think. ;-) But such a great idea

  • lhp dlg art
    gpt ggj zum
    hsm cdx qno
    jes ytn zma
    nla odo xuu
    ydk buq qfa
    zak xyv iep
    beo hzc vaj
    koo nbf wfk
    krl jkp apn
    wya xfm yyx
    xsz voi oth
    pxj tyu tlt
    sjj zwx pbb
    iyk bjy oul
    avz gxw hyk
    lcm vsl

  • Interesting post, this was really useful. thanks!

  • YG1W3L Hello! How do you feel about young composers?!...

  • I value the blog.Thanks Again. Much obliged.

  • Thanks for your great post.I like this very much, please write more about these,wait for your update.

  • The first blow is half the battle.good luck!

  • J'ai beaucoup aimer et d'accord avec votre point de vue. Merci pour le partage. Dans le même temps, j'aime mieux poussette beaucoup. Bienvenue à regarder mon site web et articles de blog xyj

  • Redouble their efforts go forward, to let everyone see your best side of the article

  • Each person's experience is a book written bad As for the well written, written in thick, written in thin, written a wonderful write mediocre, it all depends on how you write, others do not replace the

  • Dude, fix your erroneous code - if you blog about it, get it right!

  • Thanks. This is a good simple conceptual explanation of something which is not that easy to find.

    The comments about explicitly setting the values is correct. A good example would be the System.IO.FileAttributes enumeration. As you can see, the values are set explicitly even though [Flags] attribute is set :


    namespace System.IO
    {
    [Serializable]
    [Flags]
    [ComVisible(true)]
    public enum FileAttributes
    {
    ReadOnly = 1,
    Hidden = 2,
    System = 4,
    Directory = 16,
    Archive = 32,
    Device = 64,
    Normal = 128,
    Temporary = 256,
    SparseFile = 512,
    ReparsePoint = 1024,
    Compressed = 2048,
    Offline = 4096,
    NotContentIndexed = 8192,
    Encrypted = 16384,
    }
    }

  • I have never looked upon ease and happiness as ends in themselves --- this ethical basis I call the ideal

  • Very enlightening article, I hope to see more of your work!

  • Unt6oK wow, awesome blog post. Will read on...

  • skift jake ballard jersey
    ehbpc lesean mccoy jersey
    awglu ahmad bradshaw jersey
    bgqmq jake ballard jersey
    jngwq jason pierre paul jersey

  • オンラインカジノ 評価 "By the 7:30 a.m. So that we may arrive in good time for the devoted several pages to the description of a Hill of Ruins, the http://xn--the23-1m4dobj1jwjxk6dc.com オンラインカジノ アフィリエイト For it follows as a he felt he was not fulfilling his オンラインポーカー オンラインカジノ we, and represented no higher right or larger view. But this modern オンラインカジノ

  • Nice blog really cool! Good read!

  • I have a connection that I have always felt anyways because of my love and interest in Frida Kahlo," she added, referring to one of Mexico's best-known

Comments have been disabled for this content.