Typ wyliczeniowy

Typ Wyliczeniowy (Enums) #

Typ wyliczeniowy w C# jest podobny do tego z C++. Jest reprezentowany w pamięci jako typ całkowitoliczbowy i grupuje kilka stałych. W C# jest to typ bezpośredni. Domyślnie typem bazowym jest int.

Najprostsza definicja wyliczenia wygląda tak:

public enum BorderSide 
{
    Left, 
    Right, 
    Top, 
    Bottom
}

W tym przypadku do elementów wyliczenia zostaną przypisane stałe typu int: 0, 1, 2, 3.

Możemy zmienić zarówno typ pod spodem wyliczenia, jak i przypisane stałe:

public enum BorderSide : byte
{
    Left = 1, 
    Right, 
    Top = 65, 
    Bottom
}

Typem bazowym może być dowolny typ całkowitoliczbowy, który ‘pomieści’ wszystkie stałe. Stałe bez jawnie przypisanej wartości są kolejno o 1 większe od poprzedniej.

Konwersja między typami liczbowymi #

Typ wyliczeniowy możemy jawnie zrzutować z i do odpowiadającego mu typu liczbowego. Wartość zero można niejawnie do typu wyliczeniowego przypisać:

int i = (int) BorderSide.Top; // requires explicit cast
BorderSide side = (BorderSide) i; // requires explicit cast
BorderSide side = 0; // might assign 0 implicitly

Operacje na typie wyliczeniowym #

Typ wyliczeniowy wspiera operacje za pomocą operatorów bitowych (~, ^, &, |), arytmetycznych (+, -, ++, --, +=, -=) i porównania (!=, ==, <=, >=, <, >).

Ze względu na konwersję i operacje operatorami, typ wyliczeniowy może wyjść poza swój dozwolony zakres. Dlatego gdy sprawdzamy możliwe wartości powinniśmy spodziewać się niepoprawnej wartości.

BorderSide side = BorderSide.Bottom;
side++;

if (side == BorderSide.Right) {}
else if (side == BorderSide.Left) {}
else if (side == BorderSide.Top) {}
else if (side == BorderSide.Bottom) {}
else
{
    throw new ArgumentException($"Enum value out of bounds: {side}")
}

Flagi #

Zazwyczaj wartość wyliczenia może przyjąć jedną z wartości. Możemy też traktować wyliczenie w ten sposób, że pojedyncza wartość wyliczenia może reprezentować kombinację kilku wartości. Aby to działało poprawnie, kolejnym stałym musimy przypisać kolejne potęgi dwójki:

[Flags]
public enum BorderSides
{
    None = 0, 
    Left = 1, 
    Right = 1 << 1, 
    Top = 1 << 2, 
    Bottom = 1 << 3,
    LeftRight = Left | Right,
    TopBottom = Top | Bottom,
    All = LeftRight | TopBottom
}

Takie wyliczenia zwyczajowo oznaczamy atrybutem Flags, przede wszystkim aby zaznaczyć intencję użycia wyliczenia. Atrybut ten powoduje także, że metoda ToString poprawnie formatuje łączone wartości wyliczenia.

Aby sprawdzić, czy wartość wyliczenia zawiera którąś z opcji, używamy operacji bitowych:

BorderSides allButTop = BorderSides.All ^ BorderSides.Top;
Console.WriteLine((allButTop & BorderSides.Left) != 0);
Console.WriteLine((allButTop & BorderSides.Right) != 0);
Console.WriteLine((allButTop & BorderSides.Top) != 0);
Console.WriteLine((allButTop & BorderSides.Bottom) != 0);

Console.WriteLine(allButTop);