Перечисления в C#: как правильно использовать enum
В C# есть много крутых инструментов, которые позволяют улучшить любой код. Один из них — enum. Давайте разберёмся, что это и как с ним работать.


vlada_maestro / shutterstock
Списки перечисления (или enum) сокращают код и улучшают его читаемость. В этой статье мы создадим enum и научимся применять его эффективно.
Что такое enum в C#
Это список однотипных значений: цветов, состояний, способов выравнивания и так далее. Например, в C# существует встроенный список цветов:
//Эта надпись будет белого цвета
Console.WriteLine("Hello, World!");
//Указываем для текста синий цвет из списка ConsoleColor
Console.ForegroundColor = ConsoleColor.Blue;
//При конвертации в строку выводится идентификатор цвета
Console.WriteLine($"Color changed to {Console.ForegroundColor}");
//При конвертации в число - значение
Console.WriteLine($"Color code: {(int)Console.ForegroundColor}");
То есть нам не нужно вручную вводить код цвета — вместо этого мы просто выбираем значение из заранее составленного списка.
В самом enum тоже не хранится код цвета. Цифра 9 на примере выше — это индекс элемента в списке. Логика изменения цвета в нашем случае примерно такая:
//Программа проверяет, какой цвет выбран
if(ForegroundColor == ConsoleColor.Blue)
{
//Далее программа определяет RGB-код синего цвета
color = new Color(0, 0, 255);
}
//Вывод переданного текста в новом цвете
WriteLine(text, color);
Как создать enum в C#
Создайте отдельный файл и назовите его так, чтобы понять, какой это список. Например, Direction.cs:
public enum Direction
{
North, //0
South, //1
East, //2
West, //3
None //4
}
После объявления нового enum он используется как тип данных:
Direction d = Direction.North;
Вы можете указать и какие-то собственные значения для элементов. Например, коды ответа веб-сервера:
public enum Response
{
OK = 200,
Forbidden = 403,
NotFound = 404,
InternalServerError = 500,
BadGateway = 502
}
По умолчанию тип значения — int, но он изменяется на любой другой целочисленный тип:
public enum Days : byte
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Как использовать enum в C#
Самый простой пример — конструкции if и switch.
int y = 0;
int x = 0;
while(true)
{
Console.Clear();
Console.WriteLine($"Your position: [{x} , {y}]");
Console.WriteLine("Choose direction: ");
//Выводим все значения из Direction
foreach(Direction d in Enum.GetValues(typeof(Direction)))
{
Console.WriteLine($"{(int)d} - {d}");
}
int c = Convert.ToInt32(Console.ReadLine());
//Такая проверка намного проще читается, чем если бы использовались просто числа
switch((Direction)c)
{
case Direction.North:
y++;
break;
case Direction.South:
y--;
break;
case Direction.East:
x++;
break;
case Direction.West:
x--;
break;
}
}
Вот результат работы такой программы:
Также вы можете использовать enum вместе с полиморфизмом.
//Легко читается без каких-либо комментариев
item.Set(ItemType.Food);
item.Set(ItemState.InInventory);
//Длинные названия методов, непонятные аргументы
item.SetType(false, false, true);
item.SetState(false, true, false);
//Использование аксессоров упрощает изменение значений, но не решает проблему с непонятными аргументами в конструкторе
item.IsFood = true;
item.IsInInventory = true;
Таким образом вы получите код, который очень быстро читается. И теперь не нужно думать, какой метод использовать, — благодаря полиморфизму всё выглядит почти как человеческая речь: set item type — Food (указать тип предмета — Еда).
Другая хорошая практика — использовать enum в качестве возвращаемого типа для методов, в которых ошибка может произойти по разным причинам. Например, отправка данных на сервер.
public Response Send(string data)
{
if(string.IsNullOrEmpty(data))
{
return Response.EmptyData;
}
else if(trySend(data))
{
return Response.Success;
}
else
{
return Response.Error;
}
}
Этот метод возвращает три сообщения в зависимости от ситуации:
- Попытка отправить пустой запрос.
- Успешная отправка запроса.
- Неизвестная ошибка.
Конечно, допустимо куда больше вариантов: от ошибки базы данных до превышения времени ожидания.
Как enum помогает улучшить читаемость
Представим, что у нас есть класс Item со следующими полями:
- id — идентификатор;
- name — название;
- isWeapon — булево значение, которое говорит, является ли предмет оружием.
Все эти значения передаются объекту через конструктор, поэтому инициализация выглядит так:
Item item = new Item(1, "Sword", true);
Без enum со временем вы забудете, за что отвечает третий аргумент, и вам придётся каждый раз проверять реализацию класса, чтобы освежить память. Или вы добавите новые типы предметов, из-за чего таких аргументов (isArmor, isPotion) станет ещё больше:
Item item = new Item(1, "Potion", false, false, true);
Избежать таких неприятных моментов как раз и помогает enum: создайте перечисление ItemType и передавайте в конструктор его.
Item item = new Item(1, "Potion", ItemType.Potion);
С первого взгляда понятно, что здесь имеется в виду.
Заключение
C# — это мощный и красивый язык, который даёт разработчикам большие возможности, позволяя писать почти человеческим языком. Списки перечислений — лишь одна из таких вещей. Ещё есть лямбда-функции, делегаты, ООП и многое другое.