Enums
- System.Enum
- Special value types that specifies a group of named numeric constants.
- It has a underlying values of type int
- The constants are automatically assigned and can be specified explicitly also.
public enum BorderSide { Left, Right, Top, Bottom } static void Main() { BorderSide topSide = BorderSide.Top; bool isTop = (topSide == BorderSide.Top); isTop.Dump(); } // You may specify an alternative integral type: public enum BorderSideByte : byte { Left, Right, Top, Bottom } // You may also specify an explicit underlying value for each enum member: public enum BorderSideExplicit : byte { Left=1, Right=2, Top=10, Bottom=11 } public enum BorderSidePartiallyExplicit : byte { Left=1, Right, Top=10, Bottom }
Enum Conversions
Three ways to represent enum value are: enum member, integral value, string.
You can convert an enum instance to and from its underlying integral value with an
explicit cast. You can also explicitly cast one enum type to another. There are two reasons for the special treatment of 0 : first member of an enum is often used as the ‘default’ value and secondly for combined enum types, 0 means ‘no flags’.
public enum BorderSide { Left, Right, Top, Bottom } public enum HorizontalAlignment { Left = BorderSide.Left, Right = BorderSide.Right, Center } static void Main() { // You can convert an enum instance to and from its underlying integral value with an explicit cast: int i = (int) BorderSide.Left; i.Dump ("i"); BorderSide side = (BorderSide) i; side.Dump ("side"); bool leftOrRight = (int) side <= 2; leftOrRight.Dump ("leftOrRight"); HorizontalAlignment h = (HorizontalAlignment) BorderSide.Right; h.Dump ("h"); BorderSide b = 0; // No cast required with the 0 literal. b.Dump ("b"); }
Flags Enums
You can combine enum members. To prevent ambiguities, members of a combinable enum require explicitly assigned values, typically in powers of two.
[Flags] public enum BorderSides { None=0, Left=1, Right=2, Top=4, Bottom=8 } static void Main() { BorderSides leftRight = BorderSides.Left | BorderSides.Right; if ((leftRight & BorderSides.Left) != 0) Console.WriteLine ("Includes Left"); // Includes Left string formatted = leftRight.ToString(); // "Left, Right" BorderSides s = BorderSides.Left; s |= BorderSides.Right; Console.WriteLine (s == leftRight); // True s ^= BorderSides.Right; // Toggles BorderSides.Right Console.WriteLine (s); // Left }
Enum Operators
Addition is possible between enum and integral type but not between 2 enums.
= | == | != | > | < | >= | <= | + | - |
^ | & | | | ~ | += | -= | ++ | -- | sizeof |
[Flags] public enum BorderSides { None=0, Left=1, Right=2, Top=4, Bottom=8, LeftRight = Left | Right, TopBottom = Top | Bottom, All = LeftRight | TopBottom } static void Main() { BorderSides.All.Dump(); // The bitwise, arithmetic, and comparison operators return the result of processing // the underlying integral values: (BorderSides.All ^ BorderSides.LeftRight).Dump(); }
Type-Safety Issues
Since an enum can be cast to and from its underlying integral type, the actual value may fall outside the bounds of a legal enum member.
public enum BorderSide { Left, Right, Top, Bottom } static void Main() { // Since an enum can be cast to and from its underlying integral type, the actual value // it may have may fall outside the bounds of a legal enum member: BorderSide b = (BorderSide) 12345; Console.WriteLine (b); // 12345 BorderSide b2 = BorderSide.Bottom; b2++; // No errors Console.WriteLine (b2); // 4 (illegal value) } // An invalid BorderSide would break the following method: void Draw (BorderSide side) { if (side == BorderSide.Left) { /*...*/ } else if (side == BorderSide.Right) { /*...*/ } else if (side == BorderSide.Top) { /*...*/ } else { /*...*/ } // Assume BorderSide.Bottom } //Workaround [Flags] public enum BorderSides { Left=1, Right=2, Top=4, Bottom=8 } static bool IsFlagDefined (Enum e) { decimal d; return !decimal.TryParse (e.ToString(), out d); } static void Main() { for (int i = 0; i <= 16; i++) { BorderSides side = (BorderSides)i; Console.WriteLine (IsFlagDefined (side) + " " + side); } }
Type unification means you can implicitly cast any enum member to a System.Enum.
enum Nut { Walnut, Hazelnut, Macadamia } enum Size { Small, Medium, Large } static void Main() { Display (Nut.Macadamia); // Nut.Macadamia Display (Size.Large); // Size.Large } static void Display (Enum value) // The Enum type unifies all enums { Console.WriteLine (value.GetType().Name + "." + value.ToString()); }