#982 – An Enum Type Can Store a Maximum of 32 Flags

When you store a boolean value in a bool type, each boolean value uses 1 byte, or 8 bits–the size of a bool instance.

You can be more efficient in storing boolean values by using each bit within a chunk of memory to represent a single boolean value.  You can do this quite easily by using an enum type to store a series of flags.  In the example below, a single value of type Talents can represent unique values for up to 8 different boolean values.

        [Flags]
        public enum Talents
        {
            Singing = 1,
            Dancing = 2,
            Juggling = 4,
            JokeTelling = 8,
            DoingMagic = 16,
            RollingTongue = 32,
            StiltWalking = 64,
            DoingSplits = 128
        };

You can set various bits using the bitwise OR operator.

            Talents myTalents = Talents.JokeTelling | Talents.Juggling | Talents.StiltWalking;

            // 76 = 8 + 4 + 64
            int asInt = (int)myTalents;

Note that you can store a maximum of 32 different flags in an enumerated type, because an enum type uses 4 bytes (32 bits) of storage.

Advertisement

#198 – Enumeration Values That Set Combinations of Flags

When defining a enum type consisting of a set of flags, you normally add values limited to powers of two.  You can also add values that represent combinations of flags.  These can be used as a shortcut for setting several flags using a single value.

Here’s an example where we define several composite values.

        [Flags]
        public enum Talents
        {
            Singing = 1,
            Dancing = 2,
            SongAndDance = Singing | Dancing,
            Juggling = 4,
            JokeTelling = 8,
            DoesItAll = SongAndDance | Juggling | JokeTelling
        };

Now we can use these composite values when setting flags.

            Talents fred = Talents.Singing | Talents.Dancing;
            Talents sammy = Talents.SongAndDance;           // Same as Fred
            Talents eddie = Talents.Singing | Talents.Dancing | Talents.Juggling;
            Talents bobHope = Talents.DoesItAll;

The ToString method is also smart enough to list out the composite values, rather than the individual flags.

            Console.WriteLine(fred);       // SongAndDance
            Console.WriteLine(sammy);      // SongAndDance
            Console.WriteLine(eddie);      // SongAndDance, Juggling
            Console.WriteLine(bobHope);    // DoesItAll

#197 – Checking an Enumerated Value for the Presence of a Flag

You can combine enum type flags using the bitwise OR operator.  You can also use the bitwise AND operator to check an enumerated value for the presence of a flag.

            Talents fredTalents = Talents.Singing | Talents.Dancing;
            Talents ernieTalents = Talents.Singing | Talents.Juggling | Talents.JokeTelling;

            bool fredCanDance = (fredTalents & Talents.Dancing) == Talents.Dancing;
            bool ernieCanDance = (ernieTalents & Talents.Dancing) == Talents.Dancing;

When a Talents value is bitwise AND’d (&) with a specific flag, e.g. Talents.Dancing, every bit except for the Dancing bit is clear in the value.  The resulting value, of type Talents, is therefore either equal to 0 or to Talents.Dancing.

We could also write the last two lines as:

            bool fredCanDance = (fredTalents & Talents.Dancing) != 0;
            bool ernieCanDance = (ernieTalents & Talents.Dancing) != 0;

#196 – Using the ToString() Method on a Flags-Based Enum Type

When you use the ToString method on an enumeration type that has been defined with the Flags attribute, the method correctly decomposes the current value into its constituent flags.

Assuming the following enumeration type:

        [Flags]
        public enum Talents {
            Singing = 1,
            Dancing = 2,
            Juggling = 4,
            JokeTelling = 8};

And the following enumerated values:

            Talents wcFields = Talents.Juggling;
            Talents fredTalents = Talents.Singing | Talents.Dancing;
            Talents ernieTalents = Talents.Singing | Talents.Juggling | Talents.JokeTelling;

The ToString method, implicitly called by Console.WriteLine, produces the following output:

            Console.WriteLine(wcFields);            // Juggling
            Console.WriteLine(fredTalents);         // Singing, Dancing
            Console.WriteLine(ernieTalents);        // Singing, Juggling, JokeTelling

#195 – Using an Enum Type to Store a Set of Flags

If you represent a set of boolean values as bits in a larger word, you’ll notice that each flag can be represented by a value that is a power of two.

  • Singing = Bit 0 = 0 0 0 1 = 1
  • Dancing = Bit 1 = 0 0 1 0 = 2
  • Juggling = Bit 2 = 0 1 0 0 = 4
  • Joke-Telling = Bit 3 = 1 0 0 0 = 8

You can use an enum type to represent these flags.

        [Flags]
        public enum Talents {
            Singing = 1,
            Dancing = 2,
            Juggling = 4,
            JokeTelling = 8};

We can use a variable of type Talents to represent either a single talent:

            Talents sinatra = Talents.Singing;    // 1
            Talents wcFields = Talents.Juggling;  // 4

Or we can represent a set of talents using a bitwise OR operator:

            Talents fredTalents = Talents.Singing | Talents.Dancing;    // 1 + 2 = 3
            Talents ernieTalents = Talents.Singing | Talents.Juggling | Talents.JokeTelling;    // 1 + 4 + 8 = 13

The Flags attribute indicates that this enum type can be used to store a set of flags.  Using a different bit for each flag means that we can store any combination of flags at the same time.

#194 – Storing a Set of Boolean Values as Bits

You might want to store a set of boolean values in a single variable.  For example, you could keep track of a person’s talents, recording which talents each person has.

E.g.:

  • Fred: good at Singing, Dancing
  • Sally:  good at Dancing, Juggling
  • Ernie: good at Juggling, Joke-Telling, Singing

One way to store this information is to represent each talent with a single bit in a larger word and to then use the entire word to represent a person’s talents.  A bit value of 1 indicates that the person has the talent and 0 indicates that they do not have the talent.  Each person can have 0 or more talents.

For example, we could store information about four talents using four bits:

  • Bit 0 (rightmost) – Singing
  • Bit 1 – Dancing
  • Bit 2 – Juggling
  • Bit 3 (leftmost) = Joke-Telling

Here are the bit patterns for the sets of talents listed above (each word is 4 bits):

  • 0 0 1 1 = Dancing + Singing  (Fred)
  • 0 1 1 0 = Juggling + Dancing  (Sally)
  • 1 1 0 1 = Joke-Telling + Juggling + Singing  (Ernie)