Pages

Saturday, September 18, 2010

C# Bitwise Flag Enum

Imagine there was a requirement for a notification system, where users could select multiple days for delivery in a week (eg: MON, TUE, WED, THU, FRI, SAT, SUN). Now you could do this by having Boolean flags for each option or a better way is to use bitwise enum flags. They store very efficiently in memory and manipulation is very fast.

Before reading ahead, I would strongly suggest to read about bitwise operations here, otherwise it will be very hard to understand the logic of the example.

So lets declare our bitwise flag enum:
[Flags]
private enum DeliveryDays
{
  NONE = 0, // 0000000
  MON = 1,  // 0000001
  TUE = 2,  // 0000010
  WED = 4,  // 0000100
  THU = 8,  // 0001000
  FRI = 16, // 0010000
  SAT = 32, // 0100000
  SUN = 64, // 1000000
  WORKDAYS = MON | TUE | WED | THU | FRI,  //0011111
  WEEKENDS = SAT | SUN  //1100000
}
The [Flags] attribute indicates that an enumeration can be treated as a bit field. Do use powers of two for a enumeration's values so they can be freely combined using the bitwise OR operation. As you can see for workdays and weekends we have combined the relevant days.

Now lets write down the methods which set these flags on or off.
private DeliveryDays _selectedDays = DeliveryDays.None;

public void AddDeliveryDays(DeliveryDays days)
{
  _selectedDays |= days;
}

public void RemoveDeliveryDays(DeliveryDays days)
{
  _selectedDays &= ~days;
}


public void testDaysBitEnum()
{
  //lets select monday and tuesday
  AddDeliveryDays(DeliveryDays.MON | DeliveryDays.TUE);
  //lets change it all the work days
  AddDeliveryDays(DeliveryDays.WorkDays);
  //now lets remove monday and tuesday and add weekends
  RemoveDeliveryDays(DeliveryDays.MON | DeliveryDays.TUE);
  AddDeliveryDays(DeliveryDays.WEEKENDS);
}
As shown above we can quickly toggle multiple flags. But we also need some functionality to find which flags have been selected. In .NET framework 4.0 the enum has a method called HasFlag which does this for you. For older frameworks you can use the following method.
public bool HasFlag(DeliveryDays day)
{
  return ((_selectedDays & day) == day);
}
If you are using .NET 3.5 Framework it will be handy to add the above method as an Extension Method.

3 comments: