1. Вступ
У програмуванні часто доводиться працювати зі списками наперед відомих, обмежених варіантів. Наприклад — дні тижня, кольори світлофора, рівні складності гри, статуси замовлення. Кожен із цих варіантів зазвичай подано фіксованим значенням. Ось тут ми й підходимо ближче до нашої сьогоднішньої теми — перерахувань (enum).
Перерахування — це спеціальний тип даних, який дає змогу оголошувати набір іменованих констант.
enum — як коробка з розкладеними по комірках ярликами, де кожен ярлик — унікальне імʼя, пов’язане з числом.
- Ваш код стає читабельним і самодокументованим;
- Замість загадкових «магічних чисел» на кшталт 0, 1, 2 з’являються виразні імена: DayOfWeek.Monday або TrafficLight.Red;
- Компілятор повідомить про помилку, якщо ви спробуєте присвоїти некоректне значення;
- За кожним елементом ховається… звичайне ціле число! (Але до цього ми ще повернемося.)
2. Синтаксис оголошення перерахування
Створімо перше перерахування — типи погоди для нашого майбутнього застосунку. Ось як це виглядає:
// Перерахування погодних умов
public enum WeatherCondition
{
Sunny, // 0
Cloudy, // 1
Rainy, // 2
Stormy, // 3
Snowy // 4
}
- Ключове слово enum визначає новий тип.
- У фігурних дужках — імена варіантів. За замовчуванням кожному варіанту відповідає ціле число, починаючи з нуля (Sunny == 0, Cloudy == 1 тощо).
- Можна явно задати значення:
public enum WeatherCondition
{
Sunny = 1,
Cloudy = 2,
Rainy = 4,
Stormy = 8,
Snowy = 16
}
Це зручно, якщо значення мають відповідати певним зовнішнім стандартам або протоколам.
3. Використання перерахувань
Уявімо, що ми написали застосунок — невеличку консольну програму, яка реагує на погоду.
// Клас застосунку
class Program
{
static void Main()
{
// Використовуємо наше перерахування для зберігання стану погоди
WeatherCondition todayWeather = WeatherCondition.Sunny;
// Виведемо на екран
Console.WriteLine($"Сьогодні погода: {todayWeather} ({(int)todayWeather})");
// А тепер зімітуємо зміну погоди
todayWeather = WeatherCondition.Rainy;
Console.WriteLine($"Ой! Погода змінилася: {todayWeather} ({(int)todayWeather})");
}
}
Що відбудеться?
Сьогодні погода: Sunny (0)
Ой! Погода змінилася: Rainy (2)
- todayWeather — це не рядок, не число, а елемент перерахування.
- Приведення типу до (int) дає змогу побачити «числовий» код цього значення.
До речі, перерахування чудово поєднуються з умовами:
if (todayWeather == WeatherCondition.Rainy)
Console.WriteLine("Візьміть парасолю!");
4. Практичні сценарії використання enum
Де зустрічаються перерахування?
- У бізнес-застосунках: статуси замовлень (New, Processing, Shipped, Cancelled).
- У системах керування користувачами: рівні доступу (User, Moderator, Admin).
- В іграх: стани персонажа (Idle, Moving, Jumping, Falling).
- У GUI: кнопки, повідомлення, кольори іконок.
А якщо копнути у .NET — ви знайдете їх майже в кожному другому класі стандартної бібліотеки! Наприклад, у файлових операціях є перерахування для вказання режиму відкриття файлу (читання, запис, створення).
5. Явні значення та діапазон значень
Іноді варто перетворити набір значень типу int, що використовуються у вашому коді, на enum. Зробити це дуже просто:
public enum CompassDirection
{
North = 10,
East = 20,
South = 30,
West = 40
}
Тепер CompassDirection.North = 10, East = 20, тощо. Якщо якийсь елемент не вказано явно, він автоматично отримує значення +1 від попереднього.
Тип зберігання
За замовчуванням enum зберігається як int (4-байтове ціле число). Але ви можете вказати власний базовий тип, якщо хочете заощадити пам’ять:
public enum TinyEnum : byte
{
First, // 0
Second, // 1
Third // 2
}
Тепер кожне значення перерахування — лише один байт!
Повний список можливих типів: byte, sbyte, short, ushort, int, uint, long, ulong.
6. Перетворення між enum і числами/рядками
Перетворення enum ↔ int:
Щоб перетворити enum на int і навпаки, можна просто використати приведення типу:
WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // Отримаємо 1
WeatherCondition fromNumber = (WeatherCondition)2; // Отримаємо Rainy
Перетворення enum ↔ string:
Перетворити enum у рядок легко: достатньо викликати метод ToString().
// Перетворюємо enum у рядок
string name = WeatherCondition.Stormy.ToString(); // "Stormy"
// Перетворюємо рядок у enum за допомогою Enum.Parse
WeatherCondition parsed = (WeatherCondition)Enum.Parse(typeof(WeatherCondition), "Stormy");
// Також можна використати Enum.TryParse
WeatherCondition parsedOk;
if (Enum.TryParse("Snowy", out parsedOk))
{
Console.WriteLine(parsedOk); // Snowy
}
Типова помилка:
Якщо ви перетворите число на enum, для якого не визначено такого члена, компілятор не повідомить про помилку, але ви отримаєте «віртуальний» стан.
Наприклад:
WeatherCondition weird = (WeatherCondition)999;
Console.WriteLine(weird); // 999 (воно не перетвориться на «Unknown»!)
Отже, під час таких перетворень слід бути уважними.
7. switch і enum створені одне для одного
Перерахування (enum) чудово поєднуються з оператором switch. Це зручний і наочний спосіб «реагувати» на різні значення перерахування — без довгих «if-else».
Приклад: реакція на погоду
public enum WeatherCondition
{
Sunny,
Cloudy,
Rainy,
Stormy,
Snowy
}
WeatherCondition today = WeatherCondition.Rainy;
switch (today)
{
case WeatherCondition.Sunny:
Console.WriteLine("Сонячно! Можна йти гуляти.");
break;
case WeatherCondition.Cloudy:
Console.WriteLine("Похмуро. Можна взяти кофту.");
break;
case WeatherCondition.Rainy:
Console.WriteLine("Йде дощ. Не забудьте парасолю!");
break;
case WeatherCondition.Stormy:
Console.WriteLine("Шторм! Краще залишитися вдома.");
break;
case WeatherCondition.Snowy:
Console.WriteLine("Сніг іде — одягніть шапку!");
break;
default:
Console.WriteLine("Невідома погода...");
break;
}
- Кожен випадок (case) відповідає одному значенню перерахування.
- Якщо значення не збігається ні з одним із відомих варіантів, виконується default (це корисно, якщо раптом у змінну потрапило щось неочікуване).
Чим крута зв’язка enum + switch?
- Код читабельний: усі можливі варіанти одразу видно за списком case.
- Зручно розширювати: додали новий тип погоди — просто додайте ще один case.
- Безпека: компілятор попередить, якщо ви забули обробити всі варіанти (починаючи з C# 8.0, можна навіть увімкнути перевірку на вичерпність).
Приклад: enum з логікою для гри
public enum GameState
{
Start,
Playing,
Paused,
GameOver
}
void PrintState(GameState state)
{
switch (state)
{
case GameState.Start:
Console.WriteLine("Ласкаво просимо до гри!");
break;
case GameState.Playing:
Console.WriteLine("Гра триває. Успіхів!");
break;
case GameState.Paused:
Console.WriteLine("Пауза. Можна перепочити.");
break;
case GameState.GameOver:
Console.WriteLine("Гру завершено. Спробуйте ще раз!");
break;
default:
Console.WriteLine("Невідомий стан гри.");
break;
}
}
Поради:
- Якщо у вас багато схожих дій для кількох варіантів, їх можна об’єднувати:
switch (today)
{
case WeatherCondition.Rainy:
case WeatherCondition.Stormy:
Console.WriteLine("Не забудьте парасолю й теплий одяг!");
break;
}
- Не забувайте про default, щоб обробити неочікувані значення (наприклад, якщо хтось перетворив число на enum напряму).
- Зі switch зручно будувати «машини станів», меню й будь-які системи зі фіксованим набором варіантів.
8. Перерахування і основні методи/сервіси .NET
.NET надає чимало корисних методів для перерахувань:
- Enum.GetNames(typeof(WeatherCondition)) — отримати всі імена.
- Enum.GetValues(typeof(WeatherCondition)) — усі значення.
- Enum.IsDefined(typeof(WeatherCondition), "Rainy") — дізнатися, чи є в перерахуванні такий член.
- Документація: System.Enum
Приклад виведення всіх варіантів погоди:
foreach (var name in Enum.GetNames(typeof(WeatherCondition)))
{
Console.WriteLine(name);
}
9. Часті помилки й «підводні камені»
- Використовують «магічні числа» замість перерахувань, втрачаючи читабельність.
- Не обробляють значення, які не визначені в перерахуванні (див. пункт із перетворенням числа).
- Називають елементи перерахування невідповідно до їхнього змісту (Value1, Value2... — і вже ніхто не пам’ятає, що це означає).
- Порушують принцип єдиної відповідальності — використовують одне перерахування для різних речей.
Найкраще рішення: завжди використовуйте перерахування, коли набір варіантів є скінченним, і надавайте елементам змістовні, самодокументовані імена.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ