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, such as 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:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>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:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>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:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>The discard pattern (_) handles any value not explicitly listed. Because an enum's underlying type is an integer, a variable can hold a value that doesn't correspond to any named member. For example, (Season)99 is valid at runtime. The discard pattern ensures the switch expression handles those unexpected values safely. 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 System.FlagsAttribute:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>Combine values by using the | operator and test for individual flags by using System.Enum.HasFlag:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>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 cast expressions convert between an enum and its underlying integer type. An explicit cast uses the (Type)value syntax to tell the compiler you intend the conversion:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>Be aware that casting an integer to an enum doesn't validate whether the value matches a defined member. Use System.Enum.IsDefined to check validity when you accept numeric input from external sources.
Parse strings and iterate values
The System.Enum base class provides methods for parsing strings and iterating over all defined values:
sample · csharpdocs/csharp/fundamentals/types/snippets/enums/Program.cs
// <SwitchEnum>
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))
};
// </SwitchEnum>
// <UsingFlags>
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
// </UsingFlags>
// <Conversions>
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
// </Conversions>
// <ParseAndIterate>
// 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
// </ParseAndIterate>
// <UsingSeason>
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
// </UsingSeason>
// <BasicEnum>
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
// </BasicEnum>
// <UnderlyingType>
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
// </UnderlyingType>
// <FlagsEnum>
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
// </FlagsEnum>Use System.Enum.TryParse(System.String,System.Boolean,@) instead of [System.Enum.Parse(System.String)](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse--1) when the input might be invalid. It returns false` instead of throwing an exception.