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:
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:
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
Using Enumerations
Once you've declared an enumeration, you can use it as a type:
// 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:
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:
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:
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:
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:
// 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:
// 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
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
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
- Create an enum called
CardSuit
with members for Hearts, Diamonds, Clubs, and Spades. - Create a flags enum called
DaysOfOperation
to represent which days a business is open. - Write a function that takes an enum value and returns its string name.
- Create an enum for RGB color components, and write a function that combines them into a color.
- 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! :)