#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;
Advertisements

#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)

#193 – An Enum Type’s ToString Method Displays the Member’s Name

Normally, when you call the ToString method on a variable that stores an integer value, the value of the integer is displayed.

            int x = 42;
            Console.WriteLine(x.ToString());   // Displays: 42
            Console.WriteLine(x);     // Same thing--ToString implicitly called

If you call ToString on an enum type variable, however, the textual name of the enumerated member is displayed.

        public enum Mood {
            Crabby = -5,
            Happy = 5,
            Petulant = -2,
            Elated = 10};

        static void Main()
        {
            Mood myMood = Mood.Crabby;
            Mood dogsMood = Mood.Elated;

            Console.WriteLine(myMood);     // ToString implicitly called; displays: Crabby

            Console.WriteLine(dogsMood);   // Displays: Elated
        }

#192 – Using Non-Default Constant Values for Enumeration Members

When you define an enum type, the members contained in your enumeration take on constants starting at zero (for the first member) and then incrementing by one (for consecutive members).

        public enum Mood {
            Crabby,       // 0
            Happy,        // 1
            Petulant,     // 2
            Elated };     // 3

You can, however, specify the constant value to use for each member.  You can specify constants in any order.  Members that don’t have a value specified take on a value one greater than the previous member.

        public enum Mood { 
            Crabby = -5,       
            Happy = 5,        
            Petulant = -2,     
            Elated = 10};

        public enum Weekday
        {
            Sunday = 1,
            Monday,     // 2
            Tuesday,    // 3, etc.
            Wednesday,
            Thursday,
            Friday,
            Saturday
        };

#191 – Changing the Underlying Type of an enum

When you declare an enum, by default each enumerated value is represented internally with an int.  (System.Int32 – 4 bytes).  But you can use any of the following types: byte, sbyte, short, ushort, uint, long, or ulong.

        public enum Mood { Crabby, Happy, Petulant, Elated };   // type is int

        public enum MoodByte : byte { Crabby, Happy, Petulant, Elated };

        static void Main()
        {
            // 4 bytes
            Console.WriteLine("Each element is {0} bytes", sizeof(Mood));

            // 1 byte
            Console.WriteLine("Each element is {0} bytes", sizeof(MoodByte));
        }