Enums in .NET

Enumerations, or enums, are a special data type that enables for a variable to be a set of named constants. They provide a way to define a type that has a fixed set of possible values. This makes code more readable and less prone to errors compared to using raw integer constants.

What is an Enum?

An enum defines a set of named integral constants. Each constant in the enum is assigned a specific underlying integral value. By default, the first enumerator is assigned the value 0, and subsequent enumerators are assigned incrementing integral values. However, you can explicitly assign values to any or all enumerators.

Declaring an Enum

You declare an enum using the enum keyword, followed by the enum's name and then a comma-separated list of its members enclosed in curly braces.


public enum DayOfWeek
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
}
        

Underlying Type

By default, the underlying type of an enum is int. You can specify a different integral type (like byte, short, long, sbyte, ushort, uint, or ulong) by appending a colon and the type name after the enum name:


public enum Status : byte
{
    Pending = 0,
    Processing = 1,
    Completed = 2,
    Failed = 3
}
        

Using Enums

Once declared, you can use an enum type just like any other data type. You can declare variables of the enum type and assign them values from the enum members.


DayOfWeek today = DayOfWeek.Wednesday;
Status currentStatus = Status.Processing;

Console.WriteLine($"Today is: {today}"); // Output: Today is: Wednesday
Console.WriteLine($"Current status code: {(int)currentStatus}"); // Output: Current status code: 1
        

Accessing Enum Members

You can access enum members using the enum name followed by a dot and the member name, e.g., DayOfWeek.Friday.

Casting to and from Enum Types

You can cast an enum value to its underlying integral type, and vice versa:


// Casting enum to int
int dayValue = (int)DayOfWeek.Friday; // dayValue will be 4

// Casting int to enum
DayOfWeek selectedDay = (DayOfWeek)3; // selectedDay will be DayOfWeek.Wednesday

// Casting to an invalid integer value
Status unknownStatus = (Status)10; // This is valid, but the enum member might not exist.
Console.WriteLine($"Unknown status value: {(int)unknownStatus}"); // Output: Unknown status value: 10
        

Example: Using Enums in a Switch Statement

Enums are particularly useful in switch statements for handling different states or options in a clear and structured way.


public void ProcessDay(DayOfWeek day)
{
    switch (day)
    {
        case DayOfWeek.Saturday:
        case DayOfWeek.Sunday:
            Console.WriteLine("It's the weekend!");
            break;
        case DayOfWeek.Monday:
            Console.WriteLine("Start of the work week.");
            break;
        default:
            Console.WriteLine($"It's a weekday: {day}");
            break;
    }
}
        

Enum Flags

Sometimes, you need to combine multiple enum values. This is where enum flags come in handy. To create an enum that supports flags, you should:


[Flags]
public enum FilePermissions : byte
{
    None = 0,
    Read = 1,       // 00000001
    Write = 2,      // 00000010
    Execute = 4,    // 00000100
    All = Read | Write | Execute // 00000111 (7)
}

// Usage:
FilePermissions userPermissions = FilePermissions.Read | FilePermissions.Write;

Console.WriteLine($"User has permissions: {userPermissions}"); // Output: User has permissions: Read, Write

// Check for a specific permission
if ((userPermissions & FilePermissions.Read) == FilePermissions.Read)
{
    Console.WriteLine("User has read permission.");
}

// Check if All permissions are set
if (userPermissions == FilePermissions.All)
{
    Console.WriteLine("User has all permissions.");
}
else
{
    Console.WriteLine("User does not have all permissions.");
}
        

Important Note on Flags

When using flags, it's crucial to assign power-of-two values. If you don't, bitwise operations may not produce the expected results. Also, for flag enums, it's good practice to include a None member with a value of 0.

Enum Methods

The System.Enum class provides several useful static methods for working with enums:


// Using Enum methods
string dayName = Enum.GetName(typeof(DayOfWeek), DayOfWeek.Tuesday);
Console.WriteLine($"The name for value 2 is: {dayName}"); // Output: The name for value 2 is: Tuesday

bool isDefined = Enum.IsDefined(typeof(Status), 2);
Console.WriteLine($"Is status value 2 defined? {isDefined}"); // Output: Is status value 2 defined? True

Status parsedStatus = (Status)Enum.Parse(typeof(Status), "Completed");
Console.WriteLine($"Parsed status: {parsedStatus}"); // Output: Parsed status: Completed
        

Benefits of Using Enums

Tip: Enum and String Conversion

While Enum.Parse and Enum.GetName are useful, be mindful of case sensitivity and potential exceptions if the string doesn't match an enum member. Consider using Enum.TryParse for safer string conversions.