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());
}

Leave a Reply

Your email address will not be published. Required fields are marked *