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 41 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

TrackBack said:

# May 19, 2004 1:35 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

Daniel Cadenas said:

# September 8, 2006 2:29 PM

Alex said:

http://www.mscracks.com - software cracks, serial numbers, keygens, patches, cd keys, activation codes

# October 27, 2006 12:53 PM

Biker jacket leather said:

Wonderful and informative web site.I used information from that site its great.

My Catalogue site of Biker jacket leather

http://solisearch.net/bloghoster/?u=siniy

# November 19, 2006 4:43 PM

Unison said:

I just don't have much to say right now. Pretty much nothing seems worth doing. My mind is like an empty room. I haven't gotten anything done these days. What can I say?

# December 3, 2006 6:02 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

Michhes said:

The IL code suggests setting decorating an enumeration with the Flags attribute does not automatically assign 2^ values. The FlagsAttribute remains in the disassembled code so it's possible the runtime still fiddles the values.

My personal opinion is that implicit language features can be handy but it's better to be explicit for whoever's maintaining the code.

Starting with this enum...

[Flags]

public enum MyEnum

{

   None,

   First,

   Second,

   Third,

   Fourth,

   All = First | Second | Third | Fourth

}

...disassembles to this class:

.class public auto ansi sealed EnumBestPractices.MyEnum2

      extends [mscorlib]System.Enum

{

 .custom instance void [mscorlib]System.FlagsAttribute::.ctor() = ( 01 00 00 00 )

 .field public specialname rtspecialname int32 value__

 .field public static literal valuetype EnumBestPractices.MyEnum None = int32(0x00000000)

 .field public static literal valuetype EnumBestPractices.MyEnum First = int32(0x00000001)

 .field public static literal valuetype EnumBestPractices.MyEnum Second = int32(0x00000002)

 .field public static literal valuetype EnumBestPractices.MyEnum Third = int32(0x00000003)

 .field public static literal valuetype EnumBestPractices.MyEnum Fourth = int32(0x00000004)

 .field public static literal valuetype EnumBestPractices.MyEnum All = int32(0x00000007)

}

# March 13, 2007 1:39 AM

Stether said:

cigarettes.blogbugs.org - cigarettes blog

# May 24, 2007 2:55 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

nursing_career said:

Buenas dias - <a href="nursingcareerz.info/0.html ">nursing_career</a> - <a href="nursingcareerz.info/501.html ">nursing degree pinning ceremony</a> - <a href="nursingcareerz.info/172.html ">nj nursing license renewal</a> - <a href="nursingcareerz.info/233.html ">triservice nursing research program</a> - <a href="nursingcareerz.info/404.html ">cna training phoenix nursing home</a> - <a href="nursingcareerz.info/355.html ">sdsu nursing school</a> - <a href="nursingcareerz.info/236.html ">boise state university nursing program</a> - <a href="nursingcareerz.info/547.html ">pediatric nurse practitioner review course</a> - <a href="nursingcareerz.info/68.html ">oklahoma registered nurse practioner school</a> - <a href="nursingcareerz.info/559.html ">pediatric of nursing lecture note</a> best wishes

# September 14, 2007 7:19 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

Thomas Huijer said:

Het zal mijn Borland verleden zijn, maar ik vond de implementatie van sets in C# nogal zwak. Delphi heeft

# October 1, 2008 7:36 PM

Using Flagged Enums - Quickduck said:

Pingback from  Using Flagged Enums  - Quickduck

# November 2, 2008 6:28 PM

Cristian Vrabie said:

For Java programmers, EnumSet looks like a much more civilized alternative to bit flags, and since it's implemented with bit arrays, it's as performant: cristianvrabie.blogspot.com/.../bitflags-and-enumset.html

# January 16, 2009 11:08 AM

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

aqaq4063 said:

<b>AQ4.ru</b> - ���� ��� �������� �����. ���� �� ������� ���������� �� ������ � ������.

��� ���������� ������� ������� �� ���������� ������ ���������� ������� ���� �� �����

�������� ��� ���� � �� ���������<a href=http://aq4.ru></a>

# March 3, 2009 7:56 PM

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

gas powered scooters said:

Best  gas powered scooters for sale

www.world66.com/.../gas_powered_scoote

# June 10, 2009 8:55 PM

Enum values as bit flags « Keep it together man! said:

Pingback from  Enum values as bit flags &laquo;  Keep it together man!

# June 15, 2009 11:09 AM

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

vadya said:

Y6MROL this http://www.google.com is google

# June 29, 2009 3:20 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
Leave a Comment

(required) 

(required) 

(optional)

(required)