Edit

Share via


C# enumerations

Tip

New to developing software? Start with the Get started tutorials first. You'll encounter enums once you need to represent a fixed set of choices in your code.

Experienced in another language? C# enums work similarly to enums in Java or C++, with additional support for bit flags and pattern matching. Skim the flags and switch expression sections for C#-specific patterns.

An enumeration type (or enum) defines a set of named constants backed by an integer value. Use enums when a value must be one of a fixed set of options—days of the week, HTTP status codes, log levels, or directions. Enums make your code more readable and less error-prone than raw integer constants because the compiler enforces the named values.

Declare an enum

Define an enum with the enum keyword followed by the type name and its members:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

By default, the underlying type is int, and values start at 0 and increment by one. Season.Spring is 0, Season.Summer is 1, and so on.

Specify an underlying type and explicit values

You can choose a different integral type and assign explicit values to control the numeric representation:

enum HttpStatus : ushort
{
    OK = 200,
    NotFound = 404,
    InternalServerError = 500
}

Use explicit values when the numbers have external meaning, such as HTTP status codes or protocol identifiers. The underlying type can be any integral type except char. Use byte, short, ushort, int, uint, long, or ulong.

Use enums in switch expressions

Enums work naturally with switch expressions and pattern matching. The compiler warns you if you don't handle all members, which helps prevent bugs when you add a new value later:

static string DescribeSeason(Season season) => season switch
{
    Season.Spring => "Flowers bloom and temperatures rise.",
    Season.Summer => "Long days and warm weather.",
    Season.Autumn => "Leaves change color and fall.",
    Season.Winter => "Short days and cold temperatures.",
    _ => throw new ArgumentOutOfRangeException(nameof(season))
};
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));

The discard pattern (_) handles any value not explicitly listed. Pattern matching is a C# feature that tests a value against a shape or condition. In this example, each case checks whether the enum matches a specific member. Switch expressions are one of several pattern matching forms. For more information about pattern matching, see Pattern matching.

Bit flags

When an enum represents a combination of choices rather than a single choice, define each member as a power of two and apply the FlagsAttribute:

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

Combine values by using the | operator and test for individual flags by using HasFlag:

var permissions = FileAccess.Read | FileAccess.Write;

Console.WriteLine(permissions);                          // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False

The [Flags] attribute also affects ToString(). It displays combined values as comma-separated names (like Read, Write) instead of a raw number. For more information, see System.FlagsAttribute.

Convert between enums and integers

Explicit casts convert between an enum and its underlying integer type:

var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)

var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK

Be aware that casting an integer to an enum doesn't validate whether the value matches a defined member. Use Enum.IsDefined to check validity when you accept numeric input from external sources.

Parse strings and iterate values

The Enum base class provides methods for parsing strings and iterating over all defined values:

// Parse a string to an enum value:
var parsed = Enum.Parse<Season>("Winter");
Console.WriteLine(parsed); // Winter

// Try to parse safely. It returns false only when the input can't be parsed. Call Enum.IsDefined to validate named members:
if (Enum.TryParse<Season>("Monsoon", out var unknown))
{
    Console.WriteLine(unknown);
}
else
{
    Console.WriteLine("'Monsoon' is not a valid Season"); // 'Monsoon' is not a valid Season
}

// Iterate over all values in an enum:
foreach (var season in Enum.GetValues<Season>())
{
    Console.WriteLine($"{season} = {(int)season}");
}
// Spring = 0
// Summer = 1
// Autumn = 2
// Winter = 3

Use Enum.TryParse<TEnum>(String, Boolean, TEnum) instead of Enum.Parse<TEnum>(String) when the input might be invalid. It returns false instead of throwing an exception.

See also