Wimdows.NET

Wim's .NET blog

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!

Posted: Apr 07 2004, 05:08 PM by Wim | with 73 comment(s)
Filed under:

Comments

Me said:

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
# April 7, 2004 12:43 PM

Wim said:

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.
# April 7, 2004 2:35 PM

Shannon J Hager said:

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?
# April 17, 2004 3:59 PM

Steve said:

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.
# May 19, 2004 4:43 PM

Steve said:

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
}
# May 19, 2004 4:47 PM

Ian Shimmings said:

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.
# June 8, 2004 9:08 AM

Peter said:

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

# August 22, 2006 9:23 AM

pharma said:

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]

<a href="http://hometown.aol.com/mevacors">mevacor</a>">http://hometown.aol.com/mevacors">mevacor</a>

[url=http://hometown.aol.com/mevacors]mevacor[/url]

<a href="http://hometown.aol.com/albenzas">albenza</a>">http://hometown.aol.com/albenzas">albenza</a>

[url=http://hometown.aol.com/albenzas]albenza[/url]

<a href="http://hometown.aol.com/viramunew">viramune</a>">http://hometown.aol.com/viramunew">viramune</a>

[url=http://hometown.aol.com/viramunew]viramune[/url]

<a href="http://hometown.aol.com/sporanoxe">sporanox</a>">http://hometown.aol.com/sporanoxe">sporanox</a>

[url=http://hometown.aol.com/sporanoxe]sporanox[/url]

<a href="http://hometown.aol.com/sumycins">sumycin</a>">http://hometown.aol.com/sumycins">sumycin</a>

[url=http://hometown.aol.com/sumycins]sumycin[/url]

<a href="http://4aricept.blogspot.com">aricept</a>">http://4aricept.blogspot.com">aricept</a>

[url=http://4aricept.blogspot.com]aricept[/url]

<a href="http://4aceon.blogspot.com">aceon</a>">http://4aceon.blogspot.com">aceon</a>

[url=http://4aceon.blogspot.com]aceon[/url]

<a href="http://4albenza.blogspot.com">albenza</a>">http://4albenza.blogspot.com">albenza</a>

[url=http://4albenza.blogspot.com]albenza[/url]

<a href="http://4aldactone.blogspot.com">aldactone</a>">http://4aldactone.blogspot.com">aldactone</a>

[url=http://4aldactone.blogspot.com]aldactone[/url]

A very interesting site, thank you very much ! My Homepage :

<a href="http://4phentermine.blogspot.com">phentermine</a>">http://4phentermine.blogspot.com">phentermine</a>

[url=http://4phentermine.blogspot.com]phentermine[/url]

# December 14, 2006 9:57 PM

Goliath said:

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

# February 11, 2007 10:14 AM

Syed Shah Lateef Ahmed said:

Great article. Found what I was searching for.

The "And" usage was good.

Thanks.

# February 23, 2007 8:23 AM

Ben said:

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

public enum CommitType {

Insert = 1,

Update = 2,

Remove = 4 };

# June 26, 2007 6:17 PM

Unknown Programmer said:

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.

# August 29, 2007 3:04 AM

shayke said:

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

{

 ...

}

# October 8, 2007 7:16 AM

Zot said:

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

}

# December 6, 2007 8:34 AM

Without the comments, this article was horrible said:

@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

# May 1, 2008 5:38 AM

Jeremy Lundy said:

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;

# May 20, 2008 8:18 PM

alexs said:

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.

# February 11, 2009 3:29 AM

Chax0 said:

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

MyColumns ^= Column.Contract;

Then, to clear all flags:

MyColumns ^= MyColumns;

# March 11, 2009 12:08 PM

Chax0 said:

Another way to check for a flag:

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

# March 12, 2009 11:14 AM

th180dude said:

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

# June 2, 2009 8:15 AM

transparent bikini said:

Best transparent bikini

# June 10, 2009 12:53 PM

tesser said:

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.

# June 23, 2009 1:07 AM

name said:

I like your work!,

# July 29, 2009 12:12 PM

name said:

Where it is possible to buy the,

# July 29, 2009 3:50 PM

name said:

So where it to find,

# July 30, 2009 1:53 AM

usedcarauction said:

amazing stuff thanx :)

# September 14, 2009 6:35 AM

c3nturion said:

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.

# February 26, 2010 4:37 AM

Thomas said:

Given the case I defined access rights like this:

[Flags]

enum AccessRights:long{

None = 0,

Read = 1,

Write = 2,

Delete = 4,

ChangePermission = 8}

and I want to remove the ChangePermission from an arbitrary combination of existing access rights, how can I do this? I didn't find a way to remove the bit except the following:

[Flags]

enum AccessRights:long{

None = 0,

Read = 1,

RemoveRead = ~(long)1,

Write = 2,

RemoveWrite = ~(long)2,

Delete = 4,

RemoveDelete = ~(long)4,

ChangePermission = 8,

RemoveChangePermission = ~(long)8}

then I can perform x = x & AccessRights.RemoveChangePermission; to remove the right of changing permissions.

Actually I don't really like it, because it is dangerous: if someone accidentally assigns x = AccessRights.RemoveRead; then the user has all access rights except read, because ~1 is 0xFFFFFFFE.

# March 24, 2010 3:50 PM

seolace said:

Nice post, thanks for writing!

# May 6, 2010 2:38 PM

kimbo petruzelli video said:

aircraft accidents videos gup videos meningomyelocele video guy metzger utube.

# May 9, 2010 6:53 AM

village lanterne yuo tube said:

gawad kalinga utube estoques video oscar video fast forward vidoe.

# May 9, 2010 2:05 PM

eructate video said:

meryl video lehmann videos hockey enforcers video jessie mccartney video.

# May 9, 2010 3:54 PM

rocky gesner vidoe said:

dein eigenes tuningvideo ginners video flatulent videos etard video.

# May 9, 2010 9:20 PM

yuo tube marabahaya said:

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

# May 10, 2010 1:00 AM

Tatane said:

At least a clear post on the 'Flags' atrribute.

Danke cheune

# May 19, 2010 4:47 AM

evanj said:

thanks that was really helpful!

# October 11, 2010 2:42 PM

SB said:

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.

# November 20, 2010 9:37 PM

jamesakadamingo said:

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

Thanks

jamesakadamingo

# January 26, 2011 11:39 AM

commission takeover said:

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

# February 6, 2011 10:55 AM

Fat Loss 4 Idiots said:

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.

# February 6, 2011 1:36 PM

Pizza said:

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.

# March 10, 2011 11:40 AM

buy backlinks said:

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

# May 25, 2011 11:50 PM

jersey shore full episodes said:

Great post thanks for the read!!

# June 7, 2011 3:25 PM

revia uk said:

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

# June 12, 2011 11:36 PM

Strattera generika kaufen said:

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

# June 25, 2011 9:35 AM

mary hushneed said:

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.

# June 26, 2011 5:56 PM

ighntir banii dvfd said:

This post will help me at my new project!

# July 4, 2011 12:43 PM

jugal panchal said:

Nice It is new for me.

Thanks

# August 4, 2011 1:28 AM

Buy Backlinks said:

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

# December 23, 2011 8:57 PM

write my essay said:

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

# January 16, 2012 3:53 PM

Ensuep said:

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

# January 29, 2012 3:22 PM

philosophy paper said:

Interesting post, this was really useful. thanks!

# February 14, 2012 7:50 AM

tensiometro said:

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

# March 4, 2012 12:44 PM

wholesale men clothing said:

I value the blog.Thanks Again. Much obliged.

# March 20, 2012 6:12 PM

ルームウェア said:

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

# April 17, 2012 4:23 AM

Juicy Couture Outlet said:

The first blow is half the battle.good luck!

# June 4, 2012 11:59 PM

Dental Loupes said:

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    

# June 11, 2012 10:40 PM

Tiffany Outlet said:

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

# July 2, 2012 2:09 AM

Tiffany Outlet said:

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

# July 18, 2012 9:33 PM

Anon said:

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

# July 23, 2012 2:47 PM

steve_csols said:

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,

   }

}

# July 26, 2012 5:18 AM

Tiffany Outlet said:

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

# July 29, 2012 10:33 PM

Microsoft Office 2010 said:

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

# September 12, 2012 10:00 PM

crork said:

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

# September 19, 2012 9:12 PM

Jimmycq4vl said:

skift<a href=> jake ballard jersey </a>

ehbpc<a href=> lesean mccoy jersey </a>

awglu<a href=> ahmad bradshaw jersey </a>

bgqmq<a href=> jake ballard jersey </a>

jngwq<a href=> jason pierre paul jersey </a>

# November 3, 2012 12:55 AM

govtiswd said:

オンラインカジノ 評価  "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   オンラインポーカー  <a href=http://xn--79-mg4axag2fvhmi9cc.com>オンラインカジノ </a>we, and represented no higher right or larger view. But this modern <a href=http://xn--tt-mg4axag2fvhmi9cc.com >オンラインカジノ </a>

# December 11, 2012 1:20 AM

Roofers Virginia Beach said:

Nice blog really cool!  Good read!

# December 16, 2012 11:52 PM

clarisonic said:

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

# February 22, 2013 1:24 AM