Common Type System—Enumerations
Enumerations
An enumeration (a.k.a. enum) is a special type that maps a set of names to numeric values. Using them is an alternative to embedding constants in your code and provides a higher level of nominal type safety. Enum types look much like ordinary types in metadata, although they abide by a strict set of rules as defined in the CTS. For example, defining methods or constructors on enum types is prohibited, as is implementing interfaces, and they can only have a single field to represent the value. The rules exist so that enums are performant and so languages can treat them in a certain manner. Thankfully, most languages have syntactic support to abstract these rules away (C# included).
An enum type itself derives from System.Enum, which itself derives from System.ValueType. Each is
backed by a specific primitive data type, one of Boolean, Char, Byte, Int16, Int32, Int64, SByte,
UInt16, UInt32, UInt64, IntPtr, UIntPtr, Single, and Double. Int32 is used as the default in most
languages; it provides a good compromise between storage and capability to extend the enum in the
future to support more and more values.
An instance of a given enum contains a single field representing its value. Because enums are value types, having an instance of one is essentially the same as having a value of its backing store type, except that you can refer to it by type name, and they can be coerced back and forth rather simply.
In C# you simply write the following to create a new enum:
enum Color : byte { Red, Green, Blue }
The part specifying the enum’s type as byte is optional. The C# compiler handles the necessary translation into metadata, which follows the above rules:
.class private auto ansi sealed Color extends [mscorlib]System.Enum { .field public specialname rtspecialname uint8 value__ .field public static literal valuetype Color Red = uint8(0x00) .field public static literal valuetype Color Green = uint8(0x01) .field public static literal valuetype Color Blue = uint8(0x02) }
The Color enum could then be used in a program. For example, imagine that we prompted a user to
enter in his or her favorite color. We could use the enum to present the list, parse the input, and then
pass around the selection to various routines:
class ColorPick { static void Main() { Color favorite = SelectFavoriteColor(); RespondToFavoriteColor(favorite); } static Color SelectFavoriteColor() { Color favorite = (Color)(0xff); // Loop until a valid color has been selected. do { // Display the prompt and a list of valid colors. Console.Write("Please enter your favorite color ("); foreach (string name in Enum.GetNames(typeof(Color))) Console.Write(" {0} ", name); Console.Write("): "); string input = Console.In.ReadLine(); try { favorite = (Color)Enum.Parse(typeof(Color), input, true); } catch (ArgumentException) { // User’s input didn’t match an enum name. Console.WriteLine("Bad input, please choose again!"); Console.WriteLine(); } } while (favorite == (Color)(0xff)); return favorite; } static void RespondToFavoriteColor(Color c) { // Notice that C# enables you to switch over an enum. switch (c) { case Color.Red: // Do something for people that like ‘Red’. // ... break; case Color.Green: // Do something for people that like ‘Green’. // ... break; case Color.Blue: // Do something for people that like ‘Blue’. // ... break; default: // An unrecognized color got passed in. // This is probably an error! But we need to handle it. break; } } }
Notice the use of convenience static methods like GetNames and Parse on the Enum type itself. We’ll
explore the Enum class in a bit more detail farther below.
|

