Skip to main content

C# Enumerations

Introduction

Enumerations (or enums) are a special type in C# that allow you to define a set of named constants. They provide a way to create meaningful names for numeric values, making your code more readable, maintainable, and less error-prone.

Enumerations are particularly useful when you need to represent a fixed set of options or states, such as days of the week, months, card suits, or application states.

What are Enumerations?

An enumeration is a distinct value type in C# that consists of a set of named constants. By default, these constants are assigned integer values starting from 0, but you can explicitly specify different values if needed.

Let's look at a basic example:

csharp
enum DaysOfWeek
{
Sunday, // 0
Monday, // 1
Tuesday, // 2
Wednesday, // 3
Thursday, // 4
Friday, // 5
Saturday // 6
}

In this example, DaysOfWeek is an enumeration with seven members representing the days of the week. Each member has an associated integer value, starting from 0 for Sunday and incrementing by 1 for each subsequent member.

Creating and Using Enumerations

Basic Declaration

To create an enumeration in C#, use the enum keyword followed by the name of the enumeration and a list of member names enclosed in curly braces:

csharp
enum Season
{
Spring,
Summer,
Autumn,
Winter
}

Using Enumerations

Once you've declared an enumeration, you can use it as a type:

csharp
// Declare a variable of the enum type
Season currentSeason = Season.Summer;

// Use in conditionals
if (currentSeason == Season.Winter)
{
Console.WriteLine("It's cold outside!");
}
else
{
Console.WriteLine("It's not winter yet.");
}

Output:

It's not winter yet.

Custom Values for Enum Members

By default, enum members are assigned integer values starting from 0. However, you can explicitly assign different values if needed:

csharp
enum HttpStatusCode
{
OK = 200,
Created = 201,
Accepted = 202,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404,
InternalServerError = 500
}

Now when you use these values, they correspond to the standard HTTP status codes:

csharp
HttpStatusCode status = HttpStatusCode.NotFound;
Console.WriteLine($"Status code: {status} = {(int)status}");

Output:

Status code: NotFound = 404

Specifying the Underlying Type

By default, enums use int as their underlying type, but you can specify a different integral type:

csharp
enum SmallNumbers : byte
{
One = 1,
Two = 2,
Three = 3
}

The available underlying types for enums are: byte, sbyte, short, ushort, int, uint, long, and ulong.

Advanced Enum Features

Flags Enumerations

Sometimes you want to represent a combination of enum values. For example, file attributes could be read-only, hidden, or both. C# provides the [Flags] attribute for such scenarios:

csharp
using System;

[Flags]
enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
All = Read | Write | Execute
}

class Program
{
static void Main()
{
// Combine enum values with bitwise OR
FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;

Console.WriteLine(permissions); // Outputs: Read, Write

// Check if permissions include Read
bool canRead = (permissions & FilePermissions.Read) == FilePermissions.Read;
Console.WriteLine($"Can read: {canRead}"); // True

// Check if permissions include Execute
bool canExecute = (permissions & FilePermissions.Execute) == FilePermissions.Execute;
Console.WriteLine($"Can execute: {canExecute}"); // False

// Add Execute permission
permissions |= FilePermissions.Execute;
Console.WriteLine(permissions); // Outputs: Read, Write, Execute

// Remove Write permission
permissions &= ~FilePermissions.Write;
Console.WriteLine(permissions); // Outputs: Read, Execute
}
}

Output:

Read, Write
Can read: True
Can execute: False
Read, Write, Execute
Read, Execute

Note that for a flags enum to work correctly, the values should be powers of 2 (1, 2, 4, 8, 16, etc.) to ensure each bit position represents a single flag.

Converting Between Enums and Integers

You can easily convert between enum values and their underlying numeric values:

csharp
// Enum to int (explicit cast)
Season winter = Season.Winter;
int winterValue = (int)winter;
Console.WriteLine($"Winter value: {winterValue}");

// Int to enum (explicit cast)
int springValue = 0;
Season spring = (Season)springValue;
Console.WriteLine($"Season at value {springValue}: {spring}");

Output:

Winter value: 3
Season at value 0: Spring

Parsing Enum Values from Strings

C# provides methods to convert strings to enum values:

csharp
// Parse string to enum
string seasonName = "Autumn";
Season autumnSeason = (Season)Enum.Parse(typeof(Season), seasonName);
Console.WriteLine($"Parsed season: {autumnSeason}");

// TryParse is safer as it doesn't throw an exception for invalid values
string invalidSeason = "NotASeason";
if (Enum.TryParse<Season>(invalidSeason, out Season result))
{
Console.WriteLine($"Parsed season: {result}");
}
else
{
Console.WriteLine($"Could not parse '{invalidSeason}' as a Season.");
}

Output:

Parsed season: Autumn
Could not parse 'NotASeason' as a Season.

Practical Examples

Example 1: State Management in a Game

csharp
enum GameState
{
NotStarted,
Playing,
Paused,
GameOver
}

class Game
{
private GameState currentState;

public Game()
{
currentState = GameState.NotStarted;
}

public void Start()
{
if (currentState == GameState.NotStarted || currentState == GameState.GameOver)
{
currentState = GameState.Playing;
Console.WriteLine("Game started!");
}
else
{
Console.WriteLine("Cannot start game in current state.");
}
}

public void Pause()
{
if (currentState == GameState.Playing)
{
currentState = GameState.Paused;
Console.WriteLine("Game paused!");
}
else
{
Console.WriteLine("Cannot pause game in current state.");
}
}

public void Resume()
{
if (currentState == GameState.Paused)
{
currentState = GameState.Playing;
Console.WriteLine("Game resumed!");
}
else
{
Console.WriteLine("Cannot resume game in current state.");
}
}

public void End()
{
if (currentState == GameState.Playing || currentState == GameState.Paused)
{
currentState = GameState.GameOver;
Console.WriteLine("Game over!");
}
else
{
Console.WriteLine("Cannot end game in current state.");
}
}
}

// Using the game state machine
Game game = new Game();
game.Start(); // Game started!
game.Pause(); // Game paused!
game.Resume(); // Game resumed!
game.End(); // Game over!
game.Pause(); // Cannot pause game in current state.

Example 2: Order Status Tracking System

csharp
enum OrderStatus
{
Pending,
Confirmed,
Shipped,
Delivered,
Cancelled
}

class Order
{
public int OrderId { get; private set; }
public OrderStatus Status { get; private set; }
public DateTime LastUpdated { get; private set; }

public Order(int orderId)
{
OrderId = orderId;
Status = OrderStatus.Pending;
LastUpdated = DateTime.Now;
}

public void UpdateStatus(OrderStatus newStatus)
{
// Validate status transitions
if (Status == OrderStatus.Cancelled)
{
Console.WriteLine("Cannot update a cancelled order");
return;
}

if (Status == OrderStatus.Delivered && newStatus != OrderStatus.Cancelled)
{
Console.WriteLine("Delivered order cannot be updated unless being cancelled");
return;
}

// Update the status
Console.WriteLine($"Order {OrderId} status: {Status} -> {newStatus}");
Status = newStatus;
LastUpdated = DateTime.Now;
}

public void DisplayOrderInfo()
{
Console.WriteLine($"Order ID: {OrderId}");
Console.WriteLine($"Status: {Status}");
Console.WriteLine($"Last Updated: {LastUpdated}");
}
}

// Using the order status system
Order myOrder = new Order(12345);
myOrder.DisplayOrderInfo();

// Update order status
myOrder.UpdateStatus(OrderStatus.Confirmed);
myOrder.UpdateStatus(OrderStatus.Shipped);
myOrder.UpdateStatus(OrderStatus.Delivered);

// Try to update a delivered order
myOrder.UpdateStatus(OrderStatus.Shipped); // This will show an error message

Summary

Enumerations are a powerful feature in C# that allow you to define named constants, making your code more readable and maintainable. They are particularly useful for representing a set of related values, such as states, options, or categories.

Key points about C# enumerations:

  • Enums are value types that inherit from System.Enum
  • By default, enum members are assigned integer values starting from 0
  • You can assign custom values to enum members
  • Enums can have different underlying integral types (byte, int, etc.)
  • The [Flags] attribute enables combining enum values using bitwise operations
  • You can convert between enum values and their underlying numeric values
  • Enums make your code more readable and help prevent errors

Exercises

  1. Create an enum called CardSuit with members for Hearts, Diamonds, Clubs, and Spades.
  2. Create a flags enum called DaysOfOperation to represent which days a business is open.
  3. Write a function that takes an enum value and returns its string name.
  4. Create an enum for RGB color components, and write a function that combines them into a color.
  5. Implement a simple state machine using enums to represent the states of a traffic light.

Further Reading



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)