Enumerated Types as Bitflags

There’s been a lot of blogging going on about the values of Enums.   One of my favorite articles on the subject has always been Extolling the Virtues of Enumerated Types that appeared in 2001 in msdn magazine.   But before I can say, “And that’s about all I have to say about that“ Forrest Gump Style, I’ve got to mention using enums with Bitwise operations.  This is something that I use often to express a value that is a composite of other possible values. 


For Example, I use this is with my ContainerWatch application here at the Virginia International Terminals.  I need  store which Container event a user wants to receive email notifications for.   They can elect to receive all, none or any combination of the following events, which are represented in the following enum:


[Flags]
public
enum
WatchListEventEnum
{
  None = 0×00,               //  Binary 000000
  Arrive = 0×01,             //  Binary 000001
  Ready = 0×04,              //  Binary 000100
  Depart = 0×02,             //  Binary 000010
  FumigationComplete = 0×08, //  Binary 001000
  TermTermOut = 0×10,        //  Binary 010000
  TermTermIn = 0×20          //  Binary 100000
}


Now I want to store this information in a SQL Server table, and I do have them also stored in a SQL Tables as integers, but I don’t want to deal with join tables to see which events users are watching for which shipping container.  So, I instead store one int value, which is a bitwise OR of all of the events they’ve chosen.  I can use the following logic to determine if a given event is represented in a given int value. 


public static bool IsWatchListEvent(int bitmask, WatchListEventEnum evt)
{
   return Convert.ToBoolean(bitmask & (int)evt);
}


And if I want to get the int value to store in the database, I can use this function:


public static int GetEventBitmask(bool isArrive, bool isReady, bool isDepart, bool isFumigationComplete, bool isTermTerm)
{
  int retVal = (isArrive) ? (int) WatchListEventEnum.Arrive : 0;
  retVal |= (isReady) ? (int) WatchListEventEnum.Ready : 0;
  retVal |= (isDepart) ? (int) WatchListEventEnum.Depart : 0;
  retVal |= (isFumigationComplete) ? (int) WatchListEventEnum.FumigationComplete : 0;
  retVal |= (isTermTerm) ? (int) WatchListEventEnum.TermTermIn + (int) WatchListEventEnum.TermTermOut : 0;
  return retVal;
}


I can even use the bitwise & operator from SQL like so:


((WL_NEW_CTR_EVTS.WL_CONTAINER_EVENT_TYPE_ID & vw_ACTIVE_WATCH_CONTAINERS.WL_CONTAINER_EVENT_TYPE_BITMASK) > 0)


Now, a database purist may not advocate this approach,  but it works great for me in certain situations.  Okay. That’s about all I have to say…


-Brendan

About Brendan Tompkins

Brendan runs CodeBetter.Com and Devlicio.Us. He is a former MVP for Microsoft .NET and is president of Port Technology Services, a partner with Port Solution Integrators a provider of hardware and software integration services for the transportation and logistics industry.
This entry was posted in .NET General. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Tim McCurdy (tmccurdy@csc-papers.com)

    Hi, I was wondering if I use this method of storing Enums in one Column, do I need to have a certain Range on Values for the Enum.

    For example, I’ve noticed that if my Enum is simply 1 – 4, the Combinations of (1 | 2) = 3 and also (1 | 2 | 3) = 3. Will this yield incorrect results when I read from the Database??

  • Paul Laudeman