Enums
What you'll learn:
- declare an
enumand pick one value from its list; - describe data with a
recordand compare records by their contents; - get a changed copy of a record with a
withexpression; - check values with patterns in
isand in aswitchexpression, remembering that arms are checked from top to bottom.

Think of a delivery company's warehouse. The box size there is not written by hand but stamped on, and the rack holds exactly three stamps: "small", "medium" and "large". A stamp cannot print a word of your own, so a typo like "meduim" never gets onto a box.
Without the stamps, the size would be written by hand, and in a program it would have to be stored as a string or a number. The string "Meduim" with its typo compiles without a single warning. The number 1 tells the reader nothing: is that the small box or the medium one?
A type that has only values named in advance is called an enumeration. In C#, you declare it with the word enum:
Size box = Size.Medium;
Console.WriteLine(box); // Medium
if (box == Size.Medium)
{
Console.WriteLine("medium box"); // medium box
}
enum Size { Small, Medium, Large }Let's take the program apart line by line:
enum Size { Small, Medium, Large }declares the typeSizewith three values. Like a class, an enum is declared after the top-level statements.Size box = Size.Medium;creates a variable of typeSize. You write the value with a dot: the enum's name, then the value's name.Console.WriteLine(box)prints the value's name:Medium.box == Size.Mediumcompares two enum values and givestrue, so theifbranch runs.
Declaring an enum
Let's take the declaration enum Size { Small, Medium, Large } apart:
enumis a keyword: the name of a new type follows it;Sizeis the type's name, capitalized like a class name;Small,Medium,Largeare the members of the enum, separated by commas inside braces; they are capitalized too.
Now the compiler catches the typo. The line Size box = Size.Meduim; fails to compile with error CS0117: the type Size has no member Meduim.
A number behind each name
Inside, an enum stores a whole number of type int. The members are numbered in order from zero: Small is 0, Medium is 1, Large is 2. You get the number with an (int) cast, and a cast to the enum type leads back from a number to a member:
Console.WriteLine((int)Size.Large); // 2
Console.WriteLine((Size)1); // Medium
Console.WriteLine((int)Status.Archived); // 6
enum Status { Draft = 1, Published = 5, Archived }You can also set a number yourself, as in Draft = 1. A member without a number gets the previous member's number plus one, so Archived is 6.
Interviewers like to ask what an enum stores inside. The answer: a whole number, while the names are there for reading the code and for printing. Unless you give the number another type, it is an int. The default value of any enum is 0. If no member has the number 0, as in Status, the default value prints as the digit 0.
A number without a name
This is where the stamp analogy breaks down. You cannot use a stamp the rack doesn't have. An enum variable has no such protection: with a cast, you can put any int into it, even one without a name.
Size odd = (Size)7;
Console.WriteLine(odd); // 7
Console.WriteLine(odd switch
{
Size.Small => "S",
Size.Medium => "M",
Size.Large => "L",
_ => "unknown",
}); // unknownThe compiler doesn't check whether the number has a name: the cast is explicit, and you are responsible for it. Console.WriteLine prints a value without a name as digits, so the output is 7.
An enum variable can hold a number without a name, so a switch expression over an enum needs a _ arm even when every member has its own arm. Without it, the compiler warns with CS8524: a number without a name, such as (Size)3, is not handled.
Common mistake
A number was put into an enum variable without a cast:
Size box = 2; // ✗
Console.WriteLine(box);
enum Size { Small, Medium, Large }error CS0266: Cannot implicitly convert type 'int' to 'Size'. An explicit conversion exists (are you missing a cast?)The program doesn't compile. A number does not turn into an enum by itself; otherwise a stray 2 would quietly become a box size. You need an explicit cast, (Size)2, or better, the member's name: Size.Large. There is one exception, zero: the compiler converts the literal 0, or a const equal to zero, to any enum without a cast.
Key points
enumdeclares a type with a fixed set of named values:enum Size { Small, Medium, Large }.- Every member stands for an
int:0,1,2in order by default, and(int)Size.Largegives2. Console.WriteLineprints a member's name, and a number without a name as digits:(Size)7prints as7.- A number gets into an enum through an explicit cast:
Size box = 2;doesn't compile.