Перечисления C#

Подсказка

Вы новичок в разработке программного обеспечения? Сначала начните с учебников для начинающих. Вы увидите перечисления, когда необходимо представить фиксированный набор вариантов в коде.

Есть опыт на другом языке? Перечисления C# работают аналогично перечислениям в Java или C++, с дополнительной поддержкой битовых флагов и сопоставления шаблонов. Просмотрите разделы флагов и выражений switch для шаблонов C#.

Тип перечисления (или перечисление) определяет набор именованных констант, поддерживаемых целым числом. Используйте перечисления, если значение должно быть одним из фиксированных наборов параметров, таких как дни недели, коды состояния HTTP, уровни журнала или направления. Перечисления делают код более читаемым и менее подверженным ошибкам, чем необработанные целые константы, так как компилятор применяет именованные значения.

Объявить перечисление

Определите перечисление с enum ключевым словом, за которым следует имя типа и его члены:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

По умолчанию базовый тип — это int, и значения начинаются с 0 и затем увеличиваются по одному. Season.Spring это 0, Season.Summer это 1, и так далее.

Указание базового типа и явных значений

Вы можете выбрать другой целочисленный тип и назначить явные значения для управления числовым представлением:

enum HttpStatus : ushort
{
    OK = 200,
    NotFound = 404,
    InternalServerError = 500
}

Используйте явные значения, если числа имеют внешнее значение, например коды состояния HTTP или идентификаторы протокола. Базовый тип может быть любым целым типом , кроме char. Используйте byte, short, ushort, int, uint, long или ulong.

Использование перечислений в выражениях switch

Перечисления интуитивно работают с выражениями switch и сопоставлением шаблонов. Компилятор предупреждает вас, если вы не обрабатываете все элементы, что помогает предотвратить ошибки при добавлении нового значения позже:

static string DescribeSeason(Season season) => season switch
{
    Season.Spring => "Flowers bloom and temperatures rise.",
    Season.Summer => "Long days and warm weather.",
    Season.Autumn => "Leaves change color and fall.",
    Season.Winter => "Short days and cold temperatures.",
    _ => throw new ArgumentOutOfRangeException(nameof(season))
};
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));

Паттерн отбрасывания (_) обрабатывает любое значение, которое не указано явно. Поскольку базовый тип перечисления является целым числом, переменная может содержать значение, которое не соответствует ни одному именованному элементу. Например, (Season)99 допустимо во время выполнения. Шаблон отбрасывания гарантирует безопасную обработку выражением переключателя непредвиденных значений. Сопоставление шаблонов — это функция C#, которая проверяет значение для фигуры или условия. В этом примере каждый case проверяет, соответствует ли перечисление конкретному члену. Выражения switch — это одна из нескольких форм сопоставления шаблонов. Дополнительные сведения о сопоставлении шаблонов см. в разделе "Сопоставление шаблонов".

Битовые флаги

Когда перечисление представляет собой комбинацию вариантов, а не единственный выбор, присвойте каждому элементу значение, равное степени двойки, и примените следующий FlagsAttribute:

[Flags]
enum FileAccess
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4,
    ReadWrite = Read | Write,
    All = Read | Write | Execute
}

Объедините значения, используя оператор |, и проверьте отдельные флаги, используя HasFlag:

var permissions = FileAccess.Read | FileAccess.Write;

Console.WriteLine(permissions);                          // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False

Атрибут [Flags] также влияет ToString(). Он отображает объединенные значения как разделенные запятыми имена (например Read, Write) вместо необработанного числа. Дополнительные сведения см. в разделе System.FlagsAttribute.

Преобразование между перечислениями и целыми числами

Явные выражения приведения преобразуются между перечислением и его базовым целым типом. Явное приведение использует синтаксис (Type)value, чтобы указать компилятору на ваше намерение преобразовать.

var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)

var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK

Помните, что приведение целого числа в перечисление не проверяет, соответствует ли значение определенному члену. Используется Enum.IsDefined для проверки допустимости при принятии числовых входных данных из внешних источников.

Анализ строк и итерации значений

Базовый Enum класс предоставляет методы для синтаксического анализа строк и итерации по всем определенным значениям:

// Parse a string to an enum value:
var parsed = Enum.Parse<Season>("Winter");
Console.WriteLine(parsed); // Winter

// Try to parse safely. It returns false only when the input can't be parsed. Call Enum.IsDefined to validate named members:
if (Enum.TryParse<Season>("Monsoon", out var unknown))
{
    Console.WriteLine(unknown);
}
else
{
    Console.WriteLine("'Monsoon' is not a valid Season"); // 'Monsoon' is not a valid Season
}

// Iterate over all values in an enum:
foreach (var season in Enum.GetValues<Season>())
{
    Console.WriteLine($"{season} = {(int)season}");
}
// Spring = 0
// Summer = 1
// Autumn = 2
// Winter = 3

Используйте Enum.TryParse<TEnum>(String, Boolean, TEnum) вместо того, Enum.Parse<TEnum>(String) когда входные данные могут быть недопустимыми. Он возвращает false вместо того, чтобы вызывать исключение.

См. также