Posted by Ancestry Team on June 2, 2015 in Development
Flag of the United States of America
Official U.S. Navy photo by Photographer’s Mate 2nd Class Dennis Cantrell. Public Domain. Source: Wikimedia.org

Flag Day in the USA is just a couple of weeks away.  Flags are used to represent different things (usually nations or states).  While the things a nation’s flag stands for are more important than what flags in code represent, it’s easier to discuss how to use flags in code, so that’s what I’ll do here.

Flag enumerables (or, just flag enums) are a great way to represent many statuses / attributes / states.  The concept is pretty simple, and most developers have a very good grasp on how flags work.  So why post an article about flags when they’re easy?  There are lots of ways to get into trouble with flags, and there’s a straightforward concept that will avoid a lot of that trouble.

Flags represent a bit field.  According to the MSDN documentation on the FlagsAttribute, we should define enumerations in powers of two, to make sure the flags don’t overlap.  Flags are constants though, so we can’t define them using Math.Pow.  We have to use something that is a constant, or that the compiler can translate to a constant.  Usually when I see flags defined (including in MSDN documentation), they use raw integers, or hex values, looking something like one of the following:


[Flags]
public enum SomethingFlags
{
    ItemA = 1,
    ItemB = 2,
    ItemD = 4,
}

[Flags]
public enum SomethingFlagsHex
{
    Item1 = 0x01,
    Item2 = 0x02,
    Item3 = 0x04,
}

What’s wrong with that?  Nothing.  Not now, at least.  Things are usually in a good state when they are created.  But inevitably, someone is going to come along and need to make a change.  Sometimes a quick change introduces a problem.  An inexperienced (or rushed) developer needing to change some flags might alter the above to be something like one of the following:


[Flags]
public enum SomethingFlags
{
    ItemA = 1,
    ItemB = 2,
    ItemC = 3,
    ItemD = 4,
}

[Flags]
public enum SomethingFlagsHex
{
    Item1 = 0x01,
    Item2 = 0x02,
    Item3 = 0x04,
    Item4 = 0x08,
    Item5 = 0x16,
}

With a casual glance, both of those look right.  But they’re probably NOT what the developer intended.  In the first example, ItemC now represents ItemA and ItemB, not something unique.  In the second, Item5 has a value of 22, representing Item2, Item3 and what was supposed to be unique in Item5.

It would be nice to avoid those potential pitfalls.  It would be nice not to need to think about what the next value in the flags enum should be.  Fortunately, many languages (including C#) provide a near-foolproof way to do this.  Take the following example:


[Flags]
public enum SomethingFlagsBitShift
{
    Thing1 = 1 << 0,
    Thing2 = 1 << 1,
    Thing3 = 1 << 2,
    Thing4 = 1 << 3,
}

You’ll notice that it’s very intuitive to add the next item to the enum — The pattern is sequential.  It just so happens that bit shifting in this manner is the same as 2 being raised to a power.  Or, in equation form, the following is true:  1 << b == Math.Pow(2,b), where b is an integer such that overflow does not occur.  Another advantage to this approach is that it is easy to use high order bits.  If you want some padding between different “groups” of flags, it’s easy to do.  You may argue that you shouldn’t have groups in flags, and the purist in me agrees…  but I’ve done it, and you probably have, too…  It’s okay to admit it.  The example below shows an enum with gaps.  Notice how it’s easy to see how many places (and what values) you have in the gaps.


[Flags]
public enum HeroEquipment : Int64
{
    None = 0,
    BasicSword = 1 << 0,
    MagicSword = 1 << 1,
    // Leave room for more swords

    BasicHelmet = 1 << 10,
    MagicHelmet = 1 << 11,
    // Leave room for more helmets

    // This flags inherits from Int64, so I
    // can shift up to 63 places (total of 64 bits)
    ReservedMaxValue = 1 << 63 
}

 

The bit-shifting approach will work in many languages, but I would also like to point out a new way to do flags that should be coming in the next release of .NET.  In the May 2014 issue of MSDN Magazine, Mark Michaelis discusses a new “Binary Literal” that will be understood by the compiler.  The binary notation is another clear way to indicate where the flag is:


[Flags]
public enum SomethingFlagsBinaryLiteral
{
    Thing1 = 0b00_01,
    Thing2 = 0b00_10,
    Thing3 = 0b01_00,
    Thing4 = 0b10_00,
}

 

This notation is less concise, but much more clear and should help prevent the common mistakes that occur when adding new flag values.

I hope everyone enjoys Flag Day and takes time to reflect on the freedoms we have, and those sacrifices our progenitors made in order to secure our freedoms.