Enums
An enum gives names to integer constants while keeping them in a distinct type. Use it to represent states, modes and other named choices.
Declaration and values
Declare an enum at namespace level. Its underlying type defaults to int. The first member defaults to zero; each following member without an initializer uses the previous value plus one.
enum State
{
Idle, // 0
Running = 10,
Stopped // 11
}
Access a member through its enum name. Enum values can be stored, passed to functions, compared with values of the same enum and used in a switch.
State state = State.Running;
bool running = state == State.Running;
Static fields
An enum may own explicitly declared static fields. They are runtime fields, distinct from the enum's named compile-time values, and use the same initialization and access rules as struct static fields. Their type may be the enum itself or any other legal static-field type.
enum ConsoleColor
{
Black,
White,
public static ConsoleColor Default;
internal static int Uses = 0;
}
Enum fields must include static and end with a semicolon. They may be public, internal or private; protected forms are invalid because enums cannot be inherited.
Underlying integer type
Use : to select an integer storage type, including native types such as nint, nuint, clong and culong. Every member value, including an automatic successor, must fit that type.
enum Status : byte
{
Ok = 0,
Busy = 1,
Failed = 255
}
A member after Failed would need an explicit value: its automatic value of 256 does not fit byte. Floating-point types and bool cannot be enum storage types.
Constant expressions and aliases
Initializers may use compile-time integer expressions and other constants. Names must be unique within the enum, but two names may represent the same value.
const int FirstCode = 16;
enum Code
{
Start = FirstCode,
Begin = FirstCode, // an alias for the same value
End = FirstCode + 4
}
Cyclic constant dependencies and invalid constant operations are compilation errors. Aliases compare equal and cannot be separate labels in the same switch.
Explicit conversions
An enum does not implicitly convert to an integer or to another enum. Use cast<T> when crossing the enum/integer boundary. Arithmetic on the numeric representation also requires an explicit conversion.
int code = cast<int>(State.Running);
State restored = cast<State>(code);
Casting an integer to an enum does not require it to match a declared member. Include a default branch when handling values that may come from an integer conversion.
Values that depend on the target
sizeof, alignof and offsetof are valid in enum initializers. Their results are resolved using the selected compilation target, together with native integer widths and any following automatic values.
enum PlatformSize : nuint
{
PointerBytes = sizeof(nint),
PointerAlignment = alignof(nint)
}
A declaration may fit on one target and overflow on another. See Type layout for target selection and validation.