1. Intro
In programming, you often have to deal with lists of known, limited options. For example: days of the week, traffic light colors, game difficulty levels, order statuses. Each of these options is usually represented by a fixed value. And that's where we get to today's topic — enums (enum).
Enum is a special data type that lets you declare a set of named constants.
enum is like a box with labeled slots, where each label is a unique name tied to a number.
- Your code becomes readable and self-documenting;
- Instead of mysterious "magic numbers" like 0, 1, 2 you get expressive names: DayOfWeek.Monday or TrafficLight.Red;
- The compiler will yell at you if you try to assign an invalid value;
- Behind every element is... just a regular integer! (But we'll get back to that.)
2. Enum Declaration Syntax
Let's create our first enum — weather types for our future app. Here's what it looks like:
// Weather condition enum
public enum WeatherCondition
{
Sunny, // 0
Cloudy, // 1
Rainy, // 2
Stormy, // 3
Snowy // 4
}
- The enum keyword defines a new type.
- Inside the curly braces are the option names. By default, each option gets an integer value starting from zero (Sunny == 0, Cloudy == 1, etc.).
- You can set values explicitly:
public enum WeatherCondition
{
Sunny = 1,
Cloudy = 2,
Rainy = 4,
Stormy = 8,
Snowy = 16
}
This is handy if the values need to match some external standards or protocols.
3. Using Enums
Imagine we've written an app — a little console program that reacts to the weather.
// App class
class Program
{
static void Main()
{
// Use our enum to store the weather state
WeatherCondition todayWeather = WeatherCondition.Sunny;
// Print it out
Console.WriteLine($"Today's weather: {todayWeather} ({(int)todayWeather})");
// Now let's simulate a weather change
todayWeather = WeatherCondition.Rainy;
Console.WriteLine($"Oops! The weather changed: {todayWeather} ({(int)todayWeather})");
}
}
What happens?
Today's weather: Sunny (0)
Oops! The weather changed: Rainy (2)
- todayWeather is not a string, not a number, but an enum element.
- Casting to (int) lets you see the "numeric" code of the value.
By the way, enums work great with conditions:
if (todayWeather == WeatherCondition.Rainy)
Console.WriteLine("Take an umbrella!");
4. Practical Scenarios for enum
Where do you see enums?
- In business apps: order statuses (New, Processing, Shipped, Cancelled).
- In user management systems: access levels (User, Moderator, Admin).
- In games: character states (Idle, Moving, Jumping, Falling).
- In GUIs: buttons, messages, icon colors.
And if you dig into .NET — you'll find them in almost every other class in the standard library! For example, file operations have enums for specifying file open modes (read, write, create).
5. Explicit Values and Value Ranges
Sometimes you want to convert a set of int values used in code into an enum. That's super easy:
public enum CompassDirection
{
North = 10,
East = 20,
South = 30,
West = 40
}
Now CompassDirection.North = 10, East = 20, etc. If you skip a value, the next one gets previous + 1 automatically.
Storage Type
By default, enum is stored as an int (4-byte integer). But you can set your own base type if you want to save memory:
public enum TinyEnum : byte
{
First, // 0
Second, // 1
Third // 2
}
Now every enum value is just one byte!
Full list of possible types: byte, sbyte, short, ushort, int, uint, long, ulong.
6. Converting Between enum and Numbers/Strings
Converting enum ↔ int:
To convert an enum to int and back, just use a typecast:
WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // Gets 1
WeatherCondition fromNumber = (WeatherCondition)2; // Gets Rainy
Converting enum ↔ string:
To convert an enum to a string, just call ToString().
// Convert enum to string
string name = WeatherCondition.Stormy.ToString(); // "Stormy"
// Convert string to enum using Enum.Parse
WeatherCondition parsed = (WeatherCondition)Enum.Parse(typeof(WeatherCondition), "Stormy");
// Or use Enum.TryParse
WeatherCondition parsedOk;
if (Enum.TryParse("Snowy", out parsedOk))
{
Console.WriteLine(parsedOk); // Snowy
}
Common mistake:
If you cast a number to an enum that doesn't have a member with that value, the compiler won't yell, but you'll get a "virtual" state.
For example:
WeatherCondition weird = (WeatherCondition)999;
Console.WriteLine(weird); // 999 (it won't turn into "Unknown"!)
So, as a programmer, you gotta be careful with these conversions.
7. switch and enum Are Made for Each Other
Enums (enum) work perfectly with the switch statement. It's a handy and clear way to "react" to different enum values — no need for long "if-else" chains.
Example: reacting to weather
public enum WeatherCondition
{
Sunny,
Cloudy,
Rainy,
Stormy,
Snowy
}
WeatherCondition today = WeatherCondition.Rainy;
switch (today)
{
case WeatherCondition.Sunny:
Console.WriteLine("Sunny! Time to go for a walk.");
break;
case WeatherCondition.Cloudy:
Console.WriteLine("Cloudy. Maybe grab a sweater.");
break;
case WeatherCondition.Rainy:
Console.WriteLine("It's raining. Don't forget your umbrella!");
break;
case WeatherCondition.Stormy:
Console.WriteLine("Storm! Better stay home.");
break;
case WeatherCondition.Snowy:
Console.WriteLine("It's snowing — put on your hat!");
break;
default:
Console.WriteLine("Unknown weather...");
break;
}
- Each case matches one enum value.
- If the value doesn't match any known option, default runs (handy if someone puts something unexpected in the variable).
Why is enum + switch so good?
- Readable code: you see all possible options right in the case list.
- Easy to extend: add a new weather type — just add another case.
- Safety: the compiler warns you if you forgot to handle all options (starting with C# 8.0 you can even enable exhaustive checks).
Example: enum with game logic
public enum GameState
{
Start,
Playing,
Paused,
GameOver
}
void PrintState(GameState state)
{
switch (state)
{
case GameState.Start:
Console.WriteLine("Welcome to the game!");
break;
case GameState.Playing:
Console.WriteLine("Game is on. Good luck!");
break;
case GameState.Paused:
Console.WriteLine("Paused. Take a break.");
break;
case GameState.GameOver:
Console.WriteLine("Game over. Try again!");
break;
default:
Console.WriteLine("Unknown game state.");
break;
}
}
Tips:
- If you have a bunch of similar actions for several options, you can group them:
switch (today)
{
case WeatherCondition.Rainy:
case WeatherCondition.Stormy:
Console.WriteLine("Don't forget your umbrella and dress warmer!");
break;
}
- Don't forget about default to handle unexpected values (like if someone casts a number to enum directly).
- With switch it's easy to build "state machines", menus, and any systems with a fixed set of options.
8. Enums and Core .NET Methods/Services
.NET gives you a bunch of handy methods for enums:
- Enum.GetNames(typeof(WeatherCondition)) — get all names.
- Enum.GetValues(typeof(WeatherCondition)) — all values.
- Enum.IsDefined(typeof(WeatherCondition), "Rainy") — check if the enum has this member.
- Docs: System.Enum
Example: print all weather options:
foreach (var name in Enum.GetNames(typeof(WeatherCondition)))
{
Console.WriteLine(name);
}
9. Common Mistakes and "Gotchas"
- Using "magic numbers" instead of enums, losing readability.
- Not handling values that aren't defined in the enum (see the casting example).
- Naming enum elements without meaning (Value1, Value2... — and nobody remembers what they mean).
- Breaking single responsibility — using one enum for unrelated things.
Best solution: always use enums when you have a fixed set of options, and give elements meaningful, self-documenting names.
GO TO FULL VERSION