.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.
// 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 0Summer
has a value of 1Autumn
has a value of 2Winter
has a value of 3
Using Enumerations in Code
Once defined, you can use enumerations like any other type in C#:
// 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:
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:
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:
// 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:
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:
// 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:
// 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:
// 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:
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:
[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
- Use meaningful names for both enum type and enum values.
- Use singular nouns for the name of the enum type.
- Use PascalCase for both the enum type and enum values.
- Consider using the
[Flags]
attribute when values can be combined. - Use a prefix
None
orDefault
for the default value (usually 0) in your enum. - Document enums with XML comments to clarify the meaning of each value.
- Consider making flag enum values powers of 2 for proper bit manipulation.
- 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
orEnum.TryParse
to convert strings to enum values
Exercises
- Create an enum called
TrafficLight
with the valuesRed
,Yellow
, andGreen
. - Create a flag enum called
DaysOfWeek
that allows you to represent any combination of days. - Write a method that accepts a
DaysOfWeek
parameter and returns the number of days selected. - Create an enum for payment methods in an e-commerce application. What values would you include?
- 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! :)