C# enum guide — declare, iterate, Flags, and convert to string

An enum (enumeration) is a named set of integer constants. Enums make code more readable than magic numbers and give the compiler the ability to catch invalid values at compile time.

By default the underlying type is int and values start at 0, but both can be changed.

Declaring an Enum

C# Example Code
// Basic enum — values 0, 1, 2, 3
public enum Direction
{
    North,    // 0
    East,     // 1
    South,    // 2
    West      // 3
}

// Explicit underlying type (byte, short, int, long, etc.)
public enum HttpStatus : short
{
    Ok        = 200,
    NotFound  = 404,
    Error     = 500
}

// Partial explicit values — others continue from the last explicit value
public enum Priority
{
    Low    = 1,
    Medium,     // 2
    High,       // 3
    Critical = 10
}

Using an Enum

C# Example Code
Direction dir  = Direction.North;
HttpStatus code = HttpStatus.NotFound;

Console.WriteLine(dir);   // North
Console.WriteLine(code);  // NotFound
Console.WriteLine((short)code); // 404

// Compare
if (dir == Direction.North)
    Console.WriteLine("Heading north");

// Switch
string label = dir switch
{
    Direction.North => "↑",
    Direction.East  => "→",
    Direction.South => "↓",
    Direction.West  => "←",
    _               => "?"
};
Console.WriteLine(label); // ↑

Iterate All Values with Enum.GetValues

C# Example Code
// GetValues<T>() — C# 7.3+, preferred (no boxing)
foreach (Direction d in Enum.GetValues<Direction>())
    Console.WriteLine($"{(int)d}: {d}");

// Output:
// 0: North
// 1: East
// 2: South
// 3: West

// GetValues(typeof(T)) — works on older .NET targets
foreach (Direction d in Enum.GetValues(typeof(Direction)))
    Console.WriteLine(d);

Enum.GetNames — All Names as Strings

C# Example Code
string[] names = Enum.GetNames<Direction>();
Console.WriteLine(string.Join(", ", names));
// North, East, South, West

// Build a lookup dictionary from all values
var lookup = Enum.GetValues<HttpStatus>()
    .ToDictionary(s => (short)s, s => s.ToString());

Console.WriteLine(lookup[200]); // Ok
Console.WriteLine(lookup[404]); // NotFound

Convert to String and Parse

C# Example Code
Direction dir = Direction.South;

// Enum → string
string name   = dir.ToString();                      // "South"
string nameF  = dir.ToString("F");                   // "South"
string intStr = dir.ToString("D");                   // "2"  (decimal)
string hexStr = dir.ToString("X");                   // "00000002"

// string → Enum (throws on invalid input)
Direction parsed = Enum.Parse<Direction>("East");
Console.WriteLine(parsed); // East

// Case-insensitive parse
Direction ci = Enum.Parse<Direction>("west", ignoreCase: true);
Console.WriteLine(ci); // West

// Safe parse — use TryParse to avoid exceptions
if (Enum.TryParse<Direction>("North", out Direction result))
    Console.WriteLine(result); // North

if (!Enum.TryParse<Direction>("Nowhere", out _))
    Console.WriteLine("Invalid direction");

// int → Enum (be careful — any int is accepted)
Direction fromInt = (Direction)2;
Console.WriteLine(fromInt); // South

Enum.IsDefined — Validate a Value

C# Example Code
Console.WriteLine(Enum.IsDefined<Direction>(Direction.North)); // True
Console.WriteLine(Enum.IsDefined<Direction>((Direction)99));   // False

// Validate an integer before casting
int raw = 404;
if (Enum.IsDefined<HttpStatus>((HttpStatus)raw))
    Console.WriteLine((HttpStatus)raw); // NotFound
else
    Console.WriteLine("Unknown status code");

Flags Enum — Bitwise Combinations

Apply [Flags] when an enum value can be a combination of members. Use powers of 2 for the values.

C# Example Code
[Flags]
public enum FilePermission
{
    None    = 0,
    Read    = 1,        // 001
    Write   = 2,        // 010
    Execute = 4,        // 100
    ReadWrite = Read | Write  // 011 — convenience combination
}

// Combine permissions with |
FilePermission perm = FilePermission.Read | FilePermission.Execute;
Console.WriteLine(perm);           // Read, Execute
Console.WriteLine((int)perm);      // 5  (1 + 4)

// Test for a specific flag with HasFlag()
Console.WriteLine(perm.HasFlag(FilePermission.Read));    // True
Console.WriteLine(perm.HasFlag(FilePermission.Write));   // False

// Add a flag with |
perm |= FilePermission.Write;
Console.WriteLine(perm); // Read, Write, Execute

// Remove a flag with & ~
perm &= ~FilePermission.Execute;
Console.WriteLine(perm); // Read, Write

Enum as a Method Parameter

C# Example Code
static string Describe(HttpStatus status) => status switch
{
    HttpStatus.Ok       => "Request succeeded.",
    HttpStatus.NotFound => "Resource not found.",
    HttpStatus.Error    => "Server encountered an error.",
    _                   => $"Status {(int)status}"
};

Console.WriteLine(Describe(HttpStatus.NotFound)); // Resource not found.

Real-World Example: Order State Machine

C# Example Code
public enum OrderStatus
{
    Pending,
    Confirmed,
    Shipped,
    Delivered,
    Cancelled
}

public record Order(int Id, OrderStatus Status);

static OrderStatus Advance(OrderStatus current) => current switch
{
    OrderStatus.Pending   => OrderStatus.Confirmed,
    OrderStatus.Confirmed => OrderStatus.Shipped,
    OrderStatus.Shipped   => OrderStatus.Delivered,
    _ => throw new InvalidOperationException($"Cannot advance from {current}")
};

var order = new Order(1, OrderStatus.Pending);
Console.WriteLine(order.Status); // Pending

var next = order with { Status = Advance(order.Status) };
Console.WriteLine(next.Status);  // Confirmed

// Iterate all statuses to display a progress indicator
foreach (var status in Enum.GetValues<OrderStatus>())
{
    string marker = status <= next.Status ? "✓" : "○";
    Console.WriteLine($"{marker} {status}");
}
// ✓ Pending
// ✓ Confirmed
// ○ Shipped
// ○ Delivered
// ○ Cancelled

Quick Reference

OperationCode
Get all valuesEnum.GetValues<T>()
Get all namesEnum.GetNames<T>()
Parse string safelyEnum.TryParse<T>(str, out var val)
Convert to int(int)myEnum
Convert int to enum(MyEnum)intValue
Validate an integerEnum.IsDefined<T>((T)value)
Enum to stringmyEnum.ToString()
Test Flags bitmyEnum.HasFlag(flag)
Add a flagmyEnum |= flag
Remove a flagmyEnum &= ~flag