Enums

How do you represent "an order's status" or "a day of the week" in code? Magic numbers ( status == 2 ) and loose strings ( "shipped" ) are error-prone — a typo compiles fine and breaks at runtime. Enums give you a fixed, named set of options the compiler enforces, turning vague values into clear, typo-proof, self-documenting code.

Learn Enums in our free C# course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.

Part of the free C# course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

An enum is like the fixed set of buttons on a microwave : Defrost, Reheat, Popcorn. You can only press one of the labelled options — there's no way to "press button 7.5" or invent a button that doesn't exist. That constraint is exactly what makes it safe and obvious. Compare that to writing the mode as free text on a sticky note ("reheet"?) — a typo nobody catches until the food is cold. Enums are the labelled buttons; strings and magic numbers are the smudged sticky note.

1. Declaring & Using an Enum

Define an enum with a name and a comma-separated list of members. Behind the scenes each member is an int starting at 0 , but you mostly work with the names . Printing an enum shows the name, comparing is typo-proof, and you can cast to the underlying number whenever you need it.

2. Switching on an Enum

Enums and switch are made for each other. A switch expression maps each enum value to a result in a compact, readable block, and the _ fallback keeps you safe. You can also enumerate every value with Enum.GetValues<T>() — handy for menus or validation.

Your turn. Given a Day enum, work out whether the day is a weekend. The hint shows the exact condition.

3. Explicit Values & Parsing

You don't have to accept the default 0, 1, 2 numbering. Assign explicit values — perfect for HTTP status codes or priority levels — and any members after a set value auto-increment from it. To go the other way, Enum.TryParse safely turns a name string back into an enum, exactly like int.TryParse .

Sometimes you want several options at once — like read and write permissions. A [Flags] enum makes this clean: assign each member a power of two (1, 2, 4, 8) so each occupies its own bit, then combine them with the bitwise OR operator | and test with HasFlag . One variable now holds a whole set of options.

The trick is the power-of-two values: Read=1 , Write=2 , Execute=4 have no overlapping bits, so OR-ing them produces a unique combined number ( Read | Write = 3 ) that the runtime can still print as Read, Write .

These lines declare a Size enum and print a message for a medium size. Order them so the program prints Selected: Medium (1) .

Why: the enum type must be declared before it's used. Inside Main , chosen must be assigned before the WriteLine reads it. Medium is the second member, so its underlying value is 1 , giving Selected: Medium (1) .

2 — members number from 0, so Red=0 , Green=1 , Blue=2 .

3 — Low is explicitly 1, so Mid auto-increments to 2 and High to 3.

False — only Read and Exec were combined, so the Write bit isn't set.

Rotate a Direction enum with modulo arithmetic, then map the final direction to a compass arrow with a switch . The outline is in the comments.

Practice quiz

What is an enum?

  • A collection that grows dynamically
  • A reference type with methods
  • A named set of related constant values
  • A kind of loop

Answer: A named set of related constant values. An enum is a named set of related constants, giving readable names the compiler checks for you instead of magic numbers or loose strings.

By default, what underlying type and starting value does an enum use?

  • int, numbered from 0
  • string, starting at "0"
  • byte, numbered from 1
  • long, numbered from -1

Answer: int, numbered from 0. By default an enum is backed by int, with members numbered 0, 1, 2... in order unless you assign explicit values.

In , what is ?

  • 0
  • 1
  • 3
  • 2

Answer: 2. Members number from 0, so Red=0, Green=1, Blue=2.

In , what is ?

  • 1
  • 3
  • 2
  • 0

Answer: 3. Low is explicitly 1, so Mid auto-increments to 2 and High to 3.

What does printing an enum value (e.g. Console.WriteLine(status)) show?

  • Its member name
  • Its underlying number
  • An empty string
  • Its memory address

Answer: Its member name. Printing an enum shows the member's name, not its number — that's what makes enums readable.

What does a [Flags] enum let one value do?

  • Hold only one option
  • Store a string
  • Combine several options at once via bitwise OR
  • Auto-sort its members

Answer: Combine several options at once via bitwise OR. A [Flags] enum lets a single value combine several options using the bitwise OR operator, so one variable holds many flags.

Why must [Flags] enum members use powers of two (1, 2, 4, 8)?

  • To save memory
  • So each option occupies its own independent bit
  • Because the compiler requires it
  • To make them sort correctly

Answer: So each option occupies its own independent bit. Powers of two give each option its own bit with no overlap, so OR-ing them produces a unique combined value and HasFlag works correctly.

Which method safely converts a string to an enum without throwing?

  • Enum.Parse
  • Convert.ToEnum
  • int.Parse
  • Enum.TryParse

Answer: Enum.TryParse. Enum.TryParse returns false on an invalid name instead of throwing, just like int.TryParse. Avoid Enum.Parse for user input.

Given and , what is ?

  • True
  • False
  • Throws
  • null

Answer: False. Only Read and Exec were combined, so the Write bit isn't set and HasFlag returns False.

Why include a case in a switch over an enum?

  • It's required syntax
  • To list every member
  • As a fallback for unexpected or invalid values
  • To improve performance

Answer: As a fallback for unexpected or invalid values. The _ discard pattern is a safe fallback for values you didn't explicitly handle (e.g. an out-of-range cast).