Flags Enumerations

Definition of Flags Enumerators

A flags enumerator enables a series of boolean values to be tied to a single datatype. Instead of assigning one of a predefined series of values to a variable, it will instead store a byte that results from the concatenation of all possible values in the series.

Unlike traditional enumerators, the actual values in a flags enumerator must be in sequence for it to work correctly. This does not refer to a base 10 sequence, but instead to a base 2 sequence. This means that the integer value expressed as base 2 must be as shown (for five values in this example): 00001 00010 00100 01000 10000. Expressed in base 10, this is 1, 2, 4, 8, 16.

You may use an empty value, but the empty value will always be false if the item contains a value. These options are concatenated by using the bitwise or operator "|" in C#, "Or" in VB.NET.

Building a Flags Enum

Say you want to express a morning checklist of five items as a flags enumerator. This might be the definition:

// C#
[ flags() ]
enum todo

{
   do_nothing           = 0,
   walk_dog             = 1,
   cook_breakfast       = 2,
   deliver_newspaper    = 4,
   visit_miss_kerbopple = 8,
   wash_covers          = 16
}
'' VB.NET
<flags()> _
Enum todo
   do_nothing           = 0
   walk_dog             = 1
   cook_breakfast       = 2
   deliver_newspaper    = 4
   visit_miss_kerbopple = 8
   wash_covers          = 16
End Enum
Note: The values that are expressed in the series were defined peviously.

Assigning Values

As mentioned earlier, the unary or operator can concatenate values to create a result. For example, I can declare a todo item for Monday:

// C#
todo onMonday = ( walk_dog | cook_breakfast | wash_covers );
'' VB.NET
Dim onMonday As todo = ( walk_dog Or cook_breakfast Or wash_covers )

When this codeset is run, clr is actually evaluating the following:

00001 or 00100 or 10000.

The result of this operation would be 10101 (bitwise or will toggle a 1 if either or both binary digits in the sequence are true(1)). To put it another way:

0 0 0 0 1
0 0 1 0 0
1 0 0 0 0
1 0 1 0 1

For each digit, yield 1 where at least 1 in sequence is 1.

Say I have a variable of type todo that actually reflects what IS DONE.

todo is_done = do_nothing;
  1. For each item on the list, I concatenate the value of that item:
  2. // C#
    // assuming new_item is passed as a parameter and is of type todo.
    is_done = is_done | new_item;
    
    '' VB.Net
    '' assuming new_item is passed as a parameter and is of type todo.
    is_done = is_done Or new_item
    
  3. Because I forgot to walk the dog, he made a mess on my nice clean covers:
  4. // C#
    is_done = is_done | todo.wash_covers;
    is_done = is_done | todo.wash_covers;
    
    '' VB.Net
    is_done = is_done Or todo.wash_covers
    is_done = is_done Or todo.wash_covers
    
  5. The comparison would look like this:
  6. 10000 | 10000.
  7. The result would be 10000 because you are using a bitwise or, and 1 or 1 yields 1.

Testing Values

There are many means of testing to see whether (for the sake of this article) I washed the covers. Some are available online at MSDN, but I did not find those particularly useful. I am going to demonstrate the means that I found to be most appropriate.

Looking binary

test 1( 10000 is of 11000 ) test 2 (00100 is of 11000).

If I evaluate ( 10000 | 11000 ), I will get 11000. If I evaluate ( 00100 | 11000 ), I will get 11100.

This means that if I place the bitwise or between any two binary sequences, the result will be a binary sequence where each bit reflects whether at least one sequence is set to 1 in that exact position. If all of the 1s in sequence 1 are reflected as 1s in sequence 2 (as is the case in the first example), sequence 2's value will be the return value. The same applies in the reverse (all of sequence 2's 1s are reflected in sequence 1).

Expressed as flags

Consider:

// C#
todo for_monday = ( todo.walk_dog | todo.cook_breakfast |
                    todo.deliver_newspaper )
'' VB.Net
Dim for_monday As todo= ( todo.walk_dog Or todo.cook_breakfast Or todo.deliver_newspaper )

(for_monday | todo.wash_covers in c# ) (for_monday Or todo.wash_covers in VB.Net ) yields a different value. for_monday | todo.walk_dog yields for_monday. This is the case because, in appending the additional flags, no change was made. You now can express this in a function that will return true if the option has been completed.

// C#
bool testFlag( todo flg_test, todo option )
{
   /// do_nothing should not be compared in the same way (flag 0).
   if( option == todo.do_nothing )
   return false;
   // returns true if bitwise or yields same as flg_test
   // (no new binary digits have been set to 1).
   return flg_test == ( flg_test | option );
}
'' VB.Net
Function testFlag( todo flg_test, todo option ) As Boolean
   ''' do_nothing should not be compared in the same way (flag 0).
   if option = todo.do_nothing then return false
   '' returns true if bitwise or yields same as flg_test
   '' (no new binary digits have been set to 1).
   return (flg_test = ( flg_test Or option ))
End Function

Summary

Create a flags enum by using the flags attribute and specifying values in the series. You can assign multiple flags values to a variable typed as your flags enum datatype by using the bitwise or operator as shown:

myEnum newVal = ( myEnum.value1 | myEnum.value2 );

You can append additional flags using the same format:

newVal = (newVal | myEnum.value3);

You can use the bitwise or to test whether a flag is already set. The result will be equal to the variable you are testing if the flag is already set.



About the Author

David Oldfield

I still use windows XP.

Comments

  • Confused Part 2

    Posted by Steve Scrimpshire on 03/19/2013 03:23pm

    Disregard my previous question. I just found my mistake, my function had: Private Function IsExportType(ExType As ExportType, ExTypeToTest As ExportType) As Boolean Return (ExType And ExTypeToTest) End Function And should have been: Private Function IsExportType(ExType As ExportType, ExTypeToTest As ExportType) As Boolean Return (ExType = (ExType Or ExTypeToTest)) End Function Thanks for a great tutorial.

    Reply
  • Confused about AND or OR

    Posted by Steve Scrimpshire on 03/19/2013 03:17pm

    I've been testing this in VB.net 3.5 and I seem to be getting opposite results. Here's my Enum: _ Private Enum ExportType None = 0 First = 1 Second = 2 Third = 4 End Enum Here's a sample piece I use to add the enums together as in your example if I pass more than one: If xType = basMain.ExportType.None Then xType = basMain.ExportType.First Else xType = xType Or basMain.ExportType.First End If If xType = basMain.ExportType.None Then xType = basMain.ExportType.Third Else xType = xType Or basMain.ExportType.Third End If And here's my function to check for the existence of it in the "concatenated" enum: Private Function IsExportType(ExType As ExportType, ExTypeToTest As ExportType) As Boolean Return (ExType And ExTypeToTest) End Function Note that I had to do "And" in my IsExportType in order to get the correct result, while your example Function uses "Or". If I use "Or", as in your example, I get opposite results. I've tried using exportType = exportType And basMain.ExportType.Third, etc when building it and leaving the "Or" in the function as in your example, but then I get always False (as far as I tested). Was there just a typo in your Function example to test or am I missing something?

    Reply
  • Nice

    Posted by ooxoo11 on 12/20/2006 09:34am

    Short and clear. Thanks.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Learn How A Global Entertainment Company Saw a 448% ROI Every business today uses software to manage systems, deliver products, and empower employees to do their jobs. But software inevitably breaks, and when it does, businesses lose money -- in the form of dissatisfied customers, missed SLAs or lost productivity. PagerDuty, an operations performance platform, solves this problem by helping operations engineers and developers more effectively manage and resolve incidents across a company's global operations. …

  • Live Event Date: December 18, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this upcoming webcast …

Most Popular Programming Stories

More for Developers

RSS Feeds