Что такое Enum с атрибутом [Flags] в C#?

«Что такое Enum с атрибутом [Flags] в C#?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

[Flags] — это атрибут в C#, который указывает, что перечисление (enum) должно интерпретироваться как битовая маска (флаги). Это позволяет комбинировать несколько значений перечисления в одной переменной с помощью побитовых операций, что удобно для представления множества состояний или опций.

Основные правила создания:

  1. Значения должны быть степенями двойки (1, 2, 4, 8...), чтобы каждый флаг занимал уникальный бит.
  2. Определите значение None = 0 для представления пустого набора флагов.
  3. Можно использовать удобную запись с левым сдвигом: Read = 1 << 0, Write = 1 << 1.

Пример объявления и использования:

[Flags]
public enum FileAccessPermissions
{
    None    = 0,          // 0b_0000
    Read    = 1 << 0,     // 0b_0001
    Write   = 1 << 1,     // 0b_0010
    Execute = 1 << 2,     // 0b_0100
    Delete  = 1 << 3,     // 0b_1000

    // Можно определять комбинированные значения для удобства
    ReadWrite = Read | Write // 0b_0011
}

// Использование: комбинация флагов с побитовым ИЛИ (|)
FileAccessPermissions userPermissions = FileAccessPermissions.Read | FileAccessPermissions.Write;

// Проверка наличия флага (рекомендуемый способ)
if (userPermissions.HasFlag(FileAccessPermissions.Write))
{
    Console.WriteLine("Разрешена запись.");
}

// Альтернативная проверка с побитовым И (&)
bool canReadAndWrite = (userPermissions & FileAccessPermissions.ReadWrite) == FileAccessPermissions.ReadWrite;

// Удаление флага с помощью побитового И с инверсией (& ~)
userPermissions = userPermissions & ~FileAccessPermissions.Write;

Важно: Атрибут [Flags] в основном влияет на поведение методов ToString() (который выведет "Read, Write") и Enum.Parse(). Сама битовая арифметика работает и без него, но его использование является хорошей практикой для самодокументируемости кода.