top of page
Writer's pictureThe Tech Platform

Working with C# Enum: A Beginners Guide

Updated: Aug 29, 2023

If you're new to C# programming, you've likely experienced various data types and structures that help organize and manipulate data efficiently. Among these, the C# enum stands out offering a straightforward way to handle sets of related constant values. Whether you're looking to enhance code readability, simplify decision-making processes, or better structure your program's logic, understanding enums is a crucial step in your journey as a C# developer.


In this beginner's guide, we'll walk you through the essential concepts of C# enums. From what enums are and why they're essential to your programming toolkit, to practical examples that demonstrate how enums can be leveraged effectively, this guide will provide you with a solid foundation to start using enums confidently in your C# projects.


Let's begin!


Table of Contents:

What is an Enum and Why Do We Need It?

A C# enum, short for enumeration, is a distinct data type that defines a set of named constant values. Each value in the enum is known as an enum member and represents a specific option, state, or choice within a predefined set. Enums are valuable in programming because they provide a structured and readable way to work with a limited range of related values.


We need a C# enum as it:

  • Replace magic numbers/strings with meaningful names, enhancing code clarity.

  • Updates to enum values in one place affect all code using them.

  • Ensure valid values, preventing errors from incorrect inputs.

  • The Compiler validates enum usage, reducing runtime errors.

  • Clearly show available options, serving as concise documentation.

  • IDEs provide suggestions, speeding up coding and reducing mistakes.

  • Handle cases/options elegantly based on enum values.

  • Give context to values, aiding code comprehension.


Defining an Enum in C#

Defining an enum in C# is quite simple. You use the enum keyword followed by the name of your enum type and a set of curly braces that enclose the names of the enum members. Each enum member is associated with an underlying constant value, which can be of an integral numeric type (like int, byte, short, etc.).


Here's a basic example of defining a C# enum representing different types of vehicles

enum VehicleType
{
    Car,
    Truck,
    Motorcycle,
    Bicycle,
    Bus
}

In this example, the VehicleType enum represents various types of vehicles, including cars, trucks, motorcycles, bicycles, and buses. Each enum member (Car, Truck, etc.) is associated with an underlying integer value, starting from 0 for Car and incrementing by 1 for each subsequent member.


You can use this enum to represent and manipulate different types of vehicles in your program, making your code more readable and organized when dealing with transportation-related scenarios. For example:

class Program
{
    static void Main(string[] args)
    {
        VehicleType myVehicle = VehicleType.Car;

        switch (myVehicle)
        {
            case VehicleType.Car:
                Console.WriteLine("You're driving a car.");
                break;
            case VehicleType.Truck:
                Console.WriteLine("You're driving a truck.");
                break;
            case VehicleType.Motorcycle:
                Console.WriteLine("You're riding a motorcycle.");
                break;
            // ... other cases ...
            default:
                Console.WriteLine("You're using some form of transportation.");
                break;
        }
    }
}

This example demonstrates how enums can help make your code more structured and easily understandable when working with various types of vehicles.


C# Enum Members and Enum Values

C# enum provides a way to define a set of named constant values. Let's break down the concepts of enum members and enum values.


Enum Members:

Enum members are the distinct named values within an enum. They represent the various options, states, or choices that the enum can take. Each enum member is like a named constant that corresponds to a specific value. Enum members are defined within the enum declaration using a comma-separated list.


For example, consider an enum representing different days of the week:

enum DaysOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

In this enum, Monday, Tuesday, Wednesday, and so on are the enum members. They represent the possible values that the DaysOfWeek enum can take.


Enum Values:

Enum values are the constant integral values associated with each enum member. By default, enums are assigned integer values starting from 0 for the first member and incrementing by 1 for each subsequent member. However, you can explicitly assign values to enum members, which can be of any integral type (like int, byte, short, etc.).


In the example above, the enum values are assigned implicitly, where Monday has the value 0, Tuesday has the value 1, and so on.


Explicit value assignment:

enum Status
{
    Inactive = 0,
    Active = 1,
    Suspended = 2
}

Here, Inactive, Active, and Suspended are the enum members, and their associated values are explicitly assigned: 0, 1, and 2, respectively.


Therefore,

  • Enum Members: Named values within an enum, representing options or choices.

  • Enum Values: Associated constant integral values of enum members. Default values start from 0 and increment by 1, but you can assign specific values.


Assigning Constant Values to Enum Members

Assigning constant values to enum members in C# enum allows you to explicitly set the underlying integral values associated with each enum member. By default, enums are assigned integer values starting from 0 and increasing by 1 for each subsequent member. However, you can provide specific values to enum members, which can be particularly useful for compatibility, readability, and maintaining a specific numeric sequence.


Here's how you do it:

enum Status
{
    Inactive,       // Automatically assigned 0
    Active = 5,     // Explicitly assigned 5
    Suspended       // Automatically assigned 6 (since previous was 5)
}

In this example:

  • Inactive is assigned the value 0 by default.

  • Active is explicitly assigned the value 5.

  • Suspended is automatically assigned the next value in sequence (6), following the value assigned to Active.

Using explicit values for enum members can help you maintain compatibility when working with existing code or when communicating with other systems. It also allows you to give more meaningful values to enum members for easier understanding and better code documentation.


The Underlying Type of a C# Enum

The underlying type of a C# enum is the integral numeric type that determines the storage format and range of values for the enum members. By default, the underlying type for enums is int. However, you can explicitly specify a different integral numeric type if needed.


Default Underlying Type (int):

enum DaysOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

In this default case, each enum member is associated with an int value, starting from 0 for the first member and incrementing by 1 for each subsequent member.


Explicitly Specified Underlying Type (byte):

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

In this example, the SmallNumbers enum is assigned a byte underlying type. This means each enum member is associated with a byte value, allowing for a smaller range of values compared to the default int.


Why Specify Underlying Types:

  • Size and Memory: Specifying a smaller underlying type can save memory if you know your enum's values will fit within that range.

  • Interoperability: If you're working with external systems or languages that expect specific numeric types, specifying the underlying type can ensure compatibility.

  • Database Storage: When storing enums in databases, specifying underlying types can influence the size of the storage and improve performance.

  • Enum Conversion: The underlying type can impact how enums are converted to other numeric types.

Remember that specifying an underlying type should be done thoughtfully, considering the range of values your enum will represent and the context in which it will be used.


Bit Flags: Combining Choices with Enums

In C#, bit flags are a technique used with enums to represent combinations of choices or states using binary values. This approach allows you to efficiently store and manipulate multiple options in a single variable. Bit flags are especially useful when you need to handle multiple settings, permissions, or selections at once.


How It Works:

  • Bitwise Operators: C# provides bitwise operators like | (OR), & (AND), ^ (XOR), and ~ (NOT) to manipulate individual bits of integers.

  • Enum with Flags Attribute: To use an enum for bit flags, apply the [Flags] attribute to it. This indicates that the enum will be used for combining values.

  • Assigning Values: Each enum member's value should be a power of 2 (1, 2, 4, 8, 16, ...) to represent a unique bit position. This makes it possible to combine them without overlapping.

Syntax:

Suppose you have an enum to represent file permissions:

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

You can combine these permissions using bitwise OR:

FilePermissions myPermissions = FilePermissions.Read | FilePermissions.Write;

Code Example:

using System;

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

class Program
{
    static void Main(string[] args)
    {
        FilePermissions myPermissions = FilePermissions.Read | FilePermissions.Write;

        Console.WriteLine($"My permissions: {myPermissions}");
    }
}

In this code, the FilePermissions enum is defined with the [Flags] attribute, indicating that this enum will be used for bit flags. The Main method demonstrates how to combine enum values using bitwise OR (|) to represent multiple permissions (Read and Write in this case). The output will show the combined value of the permissions.


Benefits:

  • Compact Storage: You can store multiple options in a single integer, conserving memory.

  • Efficient Checks: Bitwise operations make it easy to check for specific flags without complex logic.

  • Flexible Combinations: Combine, remove, or toggle flags with simple bitwise operations.

Drawbacks:

  • Readability: Bitwise operations can make the code less intuitive and harder to read, especially for beginners.

  • Limited Flags: The number of distinct flags you can have is limited by the number of bits in the chosen integer type.

  • Complex Operations: Advanced operations like toggling specific flags can become complex.

Use Cases:

  • Permissions: Managing access rights for users or roles.

  • Settings: Enabling/disabling features or options.

  • States: Tracking multiple states or conditions.


Bit flags in C# enum are techniques for efficiently handling multiple options or choices. While they offer compact storage and efficient checks, they require an understanding of bitwise operations and may sacrifice readability. Use them when you need to manage combinations of values in a concise and organized manner.


Adding Functionality with Extension Methods

Extension methods in C# allow you to add new methods to existing types without modifying their source code. When it comes to enums, extension methods provide a way to enhance their functionality by attaching custom methods to them. This can be particularly useful for adding utility methods, transformations, or any behavior that makes working with enums more convenient.


Features:

  • Method Expansion: Extension methods let you expand enum capabilities without changing their original definition, useful when you can't modify source code directly.

  • Discoverability: Extension methods seem like part of the enum, making them visible in IntelliSense and code completion for better code understanding.

  • Code Organization: Group related methods in an extension class for a cleaner and organized codebase.


Example:

Let's consider an enum called Colors with extension methods:

using System;

public enum Colors
{
    Red,
    Green,
    Blue
}

public static class ColorExtensions
{
    public static string ToHex(this Colors color)
    {
        switch (color)
        {
            case Colors.Red:
                return "#FF0000";
            case Colors.Green:
                return "#00FF00";
            case Colors.Blue:
                return "#0000FF";
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Colors myColor = Colors.Green;
        string hexCode = myColor.ToHex();
        Console.WriteLine($"The hex code for {myColor} is {hexCode}");
    }
}

Output:

C# Enum

In this code, the ColorExtensions class contains the extension method ToHex, which converts enum values of the Colors enum to their corresponding hexadecimal color codes. The usage example in the Main method demonstrates how to use the extension method to convert the Colors.Green enum value to its hex code.


Advantages:

  • Add methods fitting your needs, improving readability, and reducing repetitive code.

  • Extend enums from external sources without changing the original code, ensuring compatibility and reducing conflicts.

  • Use extension methods to create modular designs, isolating extra functionality for easy maintenance.

  • Give meaningful names to extension methods, making your code self-explanatory.

Disadvantages:

  • Naming conflicts between extension methods can lead to confusion. Proper naming and organization can mitigate this.

  • Excessive extension methods can clutter code and cause confusion. Only add methods that truly enhance enum functionality.

  • Extension methods can't directly access private enum members. They work on a public interface, potentially limiting functionality.


Using Enums in Switch Statements

C# enum is handy for representing a set of constant values. Using them in switch statements can help you write cleaner and more organized code when you need to perform different actions based on enum values.


How to use Enums in Switch Statements:


1. Enum Declaration: Define the enum with meaningful member names that represent the different cases you want to handle.

enum DaysOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

2. Switch Statement: Create a switch statement and provide the enum variable as the expression to be evaluated.

DaysOfWeek today = DaysOfWeek.Wednesday;

switch (today)
{
    case DaysOfWeek.Monday:
        Console.WriteLine("It's the starte of the week!");
        break;
    case DaysOfWeek.Wednesday:
        Console.WriteLine("It's midweek!");
        break;
    case DaysOfWeek.Wednesday:
        Console.WriteLine("It's almost the weekend!");
        break;    
    default:
        Console.WriteLine("It's a Special Day");
        break;
}

Code:

using System;

enum DaysOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

class Program
{
    static void Main(string[] args)
    {
        DaysOfWeek today = DaysOfWeek.Monday;

        switch (today)
        {
            case DaysOfWeek.Monday:
                Console.WriteLine("It's the start of the week!");
                break;
            case DaysOfWeek.Wednesday:
                Console.WriteLine("It's midweek!");
                break;
            case DaysOfWeek.Friday:
                Console.WriteLine("It's almost the weekend!");
                break;    
            default:
                Console.WriteLine("It's a Special Day");
                break;
        }
    }
}

Output:

C# Enum

Benefits of Using Enums in Switch Statements:

  1. Readability: Using enums as cases instead of numerical values makes the code more self-explanatory.

  2. Avoid Magic Numbers: Enums provide meaningful labels, reducing the need for "magic numbers" in your code.

  3. Maintainability: If the enum values change, the switch cases automatically adapt without requiring manual updates.

  4. Compiler Checks: The compiler checks if all enum values are covered in the switch, reducing the risk of missing cases.


Example Use Case:

Imagine you're building a program to handle user account status messages:

using System;

enum AccountStatus
{
    Active,
    Inactive,
    Suspended
}

class Program
{
    static void Main(string[] args)
    {
        AccountStatus userStatus = AccountStatus.Active;

        switch (userStatus)
        {
            case AccountStatus.Active:
                Console.WriteLine("Your account is active.");
                break;
            case AccountStatus.Inactive:
                Console.WriteLine("Your account is currently inactive.");
                break;
            case AccountStatus.Suspended:
                Console.WriteLine("Your account has been suspended.");
                break;
            default:
                Console.WriteLine("Unknown account status.");
                break;
        }
    }
}

The above code defines an AccountStatus enum with three members (Active, Inactive, and Suspended). Then, it uses a switch statement to check the value of the userStatus variable and prints out the corresponding message based on the enum value.


Output:

C# Enum

Using enums in switch statements helps you write cleaner, more understandable code. C# Enum enhances readability and maintainability, making it easier to handle different cases based on meaningful labels rather than arbitrary values.


Here are some other places where you can use C# enums:

  • As a function parameter: You can use an enum as a function parameter to restrict the values that can be passed to the function. For example, you could have a function that takes an enum representing the days of the week as a parameter.

  • As a return value: You can use an enum as a return value to return a value that is limited to a specific set of values. For example, you could have a function that returns an enum representing the success or failure of an operation.

  • As a field in a class: You can use an enum as a field in a class to represent a property that can have a limited number of values. For example, you could have a class that represents a person and has an enum field for the person's gender.

  • As a switch statement case: You can use an enum as a switch statement case to execute different code depending on the value of the enum. This is the most common use of enums in C#.

  • As a dictionary key: You can use an enum as a dictionary key to store and retrieve values based on the enum's value. This is useful when you need to store a value that is limited to a specific set of values.

  • As a query parameter: You can use an enum as a query parameter to filter the results of a query. For example, you could query a database for all customers who have a specific credit card type.


Conclusion

C# enum makes your code more organized and expressive. You can access enum members easily, assign specific values or use defaults, work with bit flags, extend functionality through extension methods, and use enums effectively in switch statements. As a beginner, mastering enums will enhance your coding skills and help you create more versatile and understandable programs.

Comments


bottom of page