Multiple-Choice Enums

Created: April 25, 2015 Tagged As: .net, C#, Language Share:

Everyone familiar with .net programming knows that the Enum type is user to define a set of values for a property. For example, let's say you are defining a Building in code and you want to define the type of building. You may define an Enum called BuildingType like this:

public enum BuildingType
{
    Office,
    Retail,
    Residential
}
This allows a user to easily choose the type of building. At this point though, the choices are mutually exclusive - so if you have a multi-use building the code would not be able to define it.

Those of us who grew up programming C or C++ will liken Enums to CONST values on steroids since in .net they are strongly typed which prevents invalid values from being entered into a property. We will also remember performing bitwise operations on those CONST values in order to combine them. So you may be wondering if that is possible in .net Enums?

The answer is a resounding yes! By adding the [Flags] attribute and defining the values properly, BuildingType can become multiple-choice.

[Flags]
public enum BuildingType
{
    Office = 0x01,
    Retail = 0x02,
    Residential = 0x04
}
The Flags attribute tells the compiler to allow one or more values to be entered on any property using the BuildingType enum. Notice that I modified the values to represent hex numbers that, when combined, will be guaranteed to be unique. For instance, I did not use 0x03 since combining Office and Retail will result in 0x03.

Flags Enum In Action

The following code snippet show how a Building class might be defined using our BuildingType enum. The IsRetail property show how you need to work with the enum values now that the Flags attribute has been set (again, for C and C++ developers this should feel natural).

public class Building 
{
    public BuildingType BuildingType { getset; }

    public bool IsRetail
    {
        get { return ((this.BuildingType & BuildingType.Retail) == BuildingType.Retail); }
        set {
            if (value == true)
                this.BuildingType |= BuildingType.Retail;
            else
                this.BuildingType &= ~BuildingType.Retail;
        }
    }
}

You most likely would not put the IsRetail property in your own code, but that property show how to add or remove a single value while keeping the others. This is very important and incredibly useful.

Why Not Just Add More Properties?

As your Building class evolves, why not just add more properties (for example, IsCondo) rather than using a seemingly complex multiple-choice Enum? One argument I can offer is that adding a new Enum value involved changing only the code layer while leaving the data layer completely untouched!

It is also quite easy to bind an Enum to a ListControl (in this case we would use a check box list) so from a user-interface perspective, adding a new Enum value would allow the UI to auto-update as well (a new check item would just show up). That is way better than going through a bunch of UI code to determine where to add a new checkbox (or whatever) for the new property.

Look for a future article on how to bind an Enum to a list control.