Skip to main content

.NET Enumerations

Introduction

Enumerations (or enums) in .NET are a special type of value type that allows you to define a set of named constants. Rather than using arbitrary values like 0, 1, or 2 in your code, enumerations let you work with meaningful names that represent discrete values. This makes your code more readable, maintainable, and less prone to errors.

In this guide, we'll explore how to create and use enumerations in C# and .NET applications, understand their benefits, and learn best practices for working with them.

What Are Enumerations?

An enumeration is a distinct type that consists of a set of named constants called enumerators. Enumerations provide a way to represent a fixed set of values that are logically related.

For example, instead of representing days of the week with numbers (0 for Sunday, 1 for Monday, etc.), you can create an enumeration named DayOfWeek with named constants like Sunday, Monday, etc.

Creating Basic Enumerations

To define an enumeration in C#, use the enum keyword followed by the enumeration name and a list of named constants.

csharp
// Basic enum definition
public enum Season
{
Spring,
Summer,
Autumn,
Winter
}

By default, enum constants are assigned integer values starting from 0. In the Season enum above:

  • Spring has a value of 0
  • Summer has a value of 1
  • Autumn has a value of 2
  • Winter has a value of 3

Using Enumerations in Code

Once defined, you can use enumerations like any other type in C#:

csharp
// Create a variable of type Season
Season currentSeason = Season.Summer;

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

// Output: It's not winter yet.

Assigning Custom Values to Enum Constants

You can explicitly assign integer values to enum constants:

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

Now when you use these constants, they have the assigned values:

csharp
HttpStatusCode response = HttpStatusCode.OK;
Console.WriteLine($"Status code: {(int)response}"); // Output: Status code: 200

if (response == HttpStatusCode.OK)
{
Console.WriteLine("Request successful!");
}
// Output: Request successful!

Enum Underlying Types

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

csharp
// Using byte as the underlying type to save memory
public enum FilePermission : byte
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}

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

Flag Enumerations

A powerful feature of enumerations is the ability to create "flag enums" that can be combined using bitwise operations. This allows a variable to store multiple enum values simultaneously.

To create a flag enumeration, use the [Flags] attribute and assign values that are powers of 2:

csharp
using System;

[Flags]
public enum FilePermission
{
None = 0,
Read = 1, // 2^0
Write = 2, // 2^1
Execute = 4, // 2^2
All = Read | Write | Execute
}

Here's how to use flag enumerations:

csharp
// Combine flags using bitwise OR operator
FilePermission permissions = FilePermission.Read | FilePermission.Write;

// Check if a specific flag is set
bool canRead = (permissions & FilePermission.Read) == FilePermission.Read;
bool canExecute = (permissions & FilePermission.Execute) == FilePermission.Execute;

Console.WriteLine($"Can read: {canRead}"); // Output: Can read: True
Console.WriteLine($"Can execute: {canExecute}"); // Output: Can execute: False

// Add a permission
permissions |= FilePermission.Execute;
Console.WriteLine($"Permissions: {permissions}"); // Output: Permissions: Read, Write, Execute

// Remove a permission
permissions &= ~FilePermission.Write;
Console.WriteLine($"Permissions after removal: {permissions}"); // Output: Permissions after removal: Read, Execute

Converting Between Enums and Integers

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

csharp
// Convert enum to integer
Season winter = Season.Winter;
int winterValue = (int)winter;
Console.WriteLine($"Winter has value: {winterValue}"); // Output: Winter has value: 3

// Convert integer to enum
int value = 1;
Season convertedSeason = (Season)value;
Console.WriteLine($"Value 1 corresponds to: {convertedSeason}"); // Output: Value 1 corresponds to: Summer

Parsing Enums from Strings

You can convert strings to enum values using the Enum.Parse or Enum.TryParse methods:

csharp
// Using Enum.Parse (throws exception if the string doesn't match)
try
{
Season parsed = (Season)Enum.Parse(typeof(Season), "Summer");
Console.WriteLine($"Parsed enum: {parsed}"); // Output: Parsed enum: Summer
}
catch (ArgumentException)
{
Console.WriteLine("Invalid season name");
}

// Using Enum.TryParse (safer, doesn't throw exception)
if (Enum.TryParse<Season>("Autumn", out Season result))
{
Console.WriteLine($"Successfully parsed: {result}"); // Output: Successfully parsed: Autumn
}
else
{
Console.WriteLine("Failed to parse enum");
}

Real-World Applications

Example 1: State Management in a Game

Enumerations are perfect for representing different states in applications:

csharp
public enum GameState
{
MainMenu,
Playing,
Paused,
GameOver,
HighScore
}

public class Game
{
private GameState _currentState = GameState.MainMenu;

public void ProcessInput(string command)
{
switch (_currentState)
{
case GameState.MainMenu:
if (command == "start")
{
_currentState = GameState.Playing;
Console.WriteLine("Game started!");
}
break;
case GameState.Playing:
if (command == "pause")
{
_currentState = GameState.Paused;
Console.WriteLine("Game paused");
}
else if (command == "quit")
{
_currentState = GameState.GameOver;
Console.WriteLine("Game over!");
}
break;
// Additional cases...
}
}
}

Example 2: User Permissions System

Flag enumerations are ideal for permission systems:

csharp
[Flags]
public enum UserPermission
{
None = 0,
Read = 1,
Create = 2,
Update = 4,
Delete = 8,
Admin = Read | Create | Update | Delete | 16
}

public class User
{
public string Username { get; set; }
public UserPermission Permissions { get; set; }

public bool CanPerformAction(UserPermission requiredPermission)
{
// Check if user has Admin (which grants all permissions)
if ((Permissions & UserPermission.Admin) == UserPermission.Admin)
return true;

// Check for specific permission
return (Permissions & requiredPermission) == requiredPermission;
}
}

// Usage example
User regularUser = new User
{
Username = "JohnDoe",
Permissions = UserPermission.Read | UserPermission.Create
};

Console.WriteLine($"Can read: {regularUser.CanPerformAction(UserPermission.Read)}"); // Output: Can read: True
Console.WriteLine($"Can update: {regularUser.CanPerformAction(UserPermission.Update)}"); // Output: Can update: False

Best Practices for Enumerations

  1. Use meaningful names for both enum type and enum values.
  2. Use singular nouns for the name of the enum type.
  3. Use PascalCase for both the enum type and enum values.
  4. Consider using the [Flags] attribute when values can be combined.
  5. Use a prefix None or Default for the default value (usually 0) in your enum.
  6. Document enums with XML comments to clarify the meaning of each value.
  7. Consider making flag enum values powers of 2 for proper bit manipulation.
  8. Use enum values instead of magic numbers throughout your code for better readability.

Summary

Enumerations are a powerful feature in .NET that allow you to define named constants, making your code more readable and maintainable. They can represent simple sets of related constants, or with the [Flags] attribute, they can represent combinations of options. By using enumerations instead of magic numbers, your code becomes more self-documenting and less prone to errors.

Key points to remember:

  • Enums are value types and are defined using the enum keyword
  • By default, enum values start at 0, but you can assign custom values
  • Flag enums with the [Flags] attribute allow combining multiple values
  • Enums can be converted to and from their underlying numeric values
  • Use Enum.Parse or Enum.TryParse to convert strings to enum values

Exercises

  1. Create an enum called TrafficLight with the values Red, Yellow, and Green.
  2. Create a flag enum called DaysOfWeek that allows you to represent any combination of days.
  3. Write a method that accepts a DaysOfWeek parameter and returns the number of days selected.
  4. Create an enum for payment methods in an e-commerce application. What values would you include?
  5. Implement a state machine for a document using enums (e.g., Draft, UnderReview, Approved, Rejected).

Further Reading



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