JavaRush /Курсы /C# SELF /Перечисления (enum) в C#: удобные именованные константы

Перечисления (enum) в C#: удобные именованные константы

C# SELF
10 уровень , 4 лекция
Открыта

1. Введение

В программировании часто приходится оперировать списками заранее известных, ограниченных вариантов. Например: дни недели, цвета светофора, уровни сложности игры, статусы заказа. Каждый из этих вариантов обычно представлен фиксированным значением. Вот тут мы и подбираемся ближе к нашей сегодняшней теме — перечислениям (enum).

Перечисление — это специальный тип данных, который позволяет объявлять набор именованных констант.
enum — как коробка с разложенными по ячейкам ярлыками, где каждый ярлык — уникальное имя, связанное с числом.

  • Ваш код становится читаемым и самодокументируемым;
  • Вместо загадочных «магических чисел» вроде 0, 1, 2 появляются выразительные имена: DayOfWeek.Monday или TrafficLight.Red;
  • Компилятор будет ругаться, если вы попытаетесь присвоить некорректное значение;
  • За каждым элементом скрывается… обычное целое число! (Но к этому мы еще вернемся.)

2. Синтаксис объявления перечисления

Давайте создадим первое перечисление — типы погоды для нашего будущего приложения. Вот как это будет выглядеть:


// Перечисление погодных условий
public enum WeatherCondition
{
    Sunny,       // 0
    Cloudy,      // 1
    Rainy,       // 2
    Stormy,      // 3
    Snowy        // 4
}
Объявление перечисления WeatherCondition
  • Ключевое слово 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 и числами/строками

Преобразование enumint:

Чтобы преобразовать enum в int и обратно, вы можете просто использовать typecast:

WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // Получим 1

WeatherCondition fromNumber = (WeatherCondition)2; // Получим Rainy

Преобразование enumstring:

Преобразовать 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... — и уже никто не помнит, что это значит).
  • Нарушают принцип единственной ответственности — используют одно перечисление для разнородных вещей.

Лучшее решение: всегда использовать перечисления, когда есть конечный набор вариантов, и давать элементам смысловые, самодокументируемые имена.

2
Задача
C# SELF, 10 уровень, 4 лекция
Недоступна
Использование перечисления для управления настройками
Использование перечисления для управления настройками
2
Задача
C# SELF, 10 уровень, 4 лекция
Недоступна
Приложение для прогноза погоды с использованием switch
Приложение для прогноза погоды с использованием switch
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Andrey Belyakov Уровень 12
9 января 2026
Как же бесят ваши двоякие ТЗ, наймите нормального СА что ли... Почему вот снова пишется в ТЗ "Используйте switch для вывода соответствующего сообщения. Например:" Но при этом, если сраную точку не поставить проверка ругается. Слово "Например" в ТЗ означает, что вот вам пример, но ему не обязательно следовать. Если обязательно так и пишите "Программа должна вывести: ..." Честно, просто горит с такого, почти в каждой задачке такая или подобная хрень.