Enums

System.ValueType –> System.Enum

Enums store choices that are optionally related to values.
Enums are thread safe.

Best Practices

  • If there is no enum member with value 0, create a None constant.
    • (The memory used for the enum is initialized to 0 by the CLR. If you do not define a constant whose value = 0, the enum will contain an illegal value when created.)
  • When you define a method or property that takes an enum constant as a value, validate the value.
    • (A numeric value casted to the enum type will succeed even if that numeric value is not defined in the enum.)

Creating

public enum Weekdays { Monday, Tuesday, Wednesday, Thursday, Friday }

public enum Seasons
{
  None = 0,
  Summer = 1,
  Autumn = 2,
  Winter = 4,
  Spring = 8,
  All = Summer | Autumn | Winter | Spring
}

Seasons.All returns Summer, Autumn, Winter, Spring

Declaring

var theYear = Seasons.All;

Operators

The bitwise operators | and & are used to combine and intersect enum choices:

var warmTimes = Seasons.Spring & Seasons.Summer;
var startingOnEquinox = Seasons.Spring | Seasons.Autumn;

Conversions

Enums can be explicitly casted to their underlying integral type:

public enum ArrivalStatus { Late = -1, OnTime = 0, Early = 1 };

int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus) value3; // int casted to enum

int value4 = (int) status3; // enum casted to int

Using IsDefined() Before Converting

using the IsDefined method prevents assigning a value that is not a member of the enum:

if (Enum.IsDefined(typeof(ArrivalStatus), 5)) // returns False

Converting an Enum Value to its Underlying Type

ArrivalStatus foo = ArrivalStatus.Early;

var number = Convert.ChangeType(foo, Enum.GetUnderlyingType(typeof(ArrivalStatus))); // number is 1.

Parsing Enumeration Values (string -> enum)

string name = "Early";

if (Enum.TryParse<ArrivalStatus>(name, out ArrivalStatus bar)) 
{ // True
  // …
}

Iterating Enumeration Members

First, get a string array of the names of the enum members:

string[] names = Enum.GetNames(typeof(ArrivalStatus));

// Next, call Parse to convert the string to its enum value:
foreach (var name in names) 
{
  ArrivalStatus status = (ArrivalStatus) Enum.Parse(typeof(ArrivalStatus), name);
}

Iterating Enumeration Values

Like above, except call Enum.GetValues to get an array of the enum’s underlying values.

Flags Attribute

The Flags attribute allows an enum object to include multiple members of the enum.

  • Note: Requires defining enum constants in powers of 2.
  • Note: Do not define a negative number as a flag.
[Flags] public enum Pets { None=0, Dog=1, Cat=2, Bird=4, Rodent=8 };

Pets familyPets = Pets.Dog | Pets.Cat;

familyPets.HasFlag(Pets.Dog); // True.

Enum Extension Methods

Enums are defined by language structures so you cannot define custom methods for an enumeration type. However, you can use extension methods:

public enum Grades { F = 0, D = 1, C = 2, B = 3, A = 4 };

public static class Extensions 
{
  public static Grades minPassingGrade = Grades.D;

  public static bool Passing(this Grades grade) { return grade >= minPassing; }
}

Grades g1 = Grades.F;
g1.Passing() // False.