Sdílet prostřednictvím


19 Výčty

19.1 Obecné

Typ výčtu je jedinečný typ hodnoty (§8.3), který deklaruje množinu pojmenovaných konstant.

Příklad: Příklad

enum Color
{
    Red,
    Green,
    Blue
}

deklaruje typ výčtu s názvem Color členy Red, Greena Blue.

end example

19.2 Deklarace výčtu

Deklarace výčtu deklaruje nový typ výčtu. Deklarace výčtu začíná klíčovým slovem enuma definuje název, přístupnost, základní typ a členy výčtu.

enum_declaration
    : attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'?
    ;

enum_base
    : ':' integral_type
    | ':' integral_type_name
    ;

integral_type_name
    : type_name // Shall resolve to an integral type other than char
    ;

enum_body
    : '{' enum_member_declarations? '}'
    | '{' enum_member_declarations ',' '}'
    ;

Každý typ výčtu má odpovídající celočíselný typ, který se nazývá základní typ výčtu. Tento základní typ musí být schopen reprezentovat všechny hodnoty výčtu definované v výčtu. Pokud je enum_base k dispozici, explicitně deklaruje základní typ. Podkladový typ musí být jedním z celočíselných typů (§8.3.6) jiných než char. Podkladový typ může být určen buď integral_type(§8.3.5), nebo integral_type_name Řeší integral_type_name se stejným způsobem jako type_name (§7.8.1), včetně použití směrnic (§14.5).

Poznámka: Typ nelze použít jako podkladový typ, a to char buď podle klíčového slova, nebo prostřednictvím .integral_type_name koncová poznámka

Deklarace výčtu, která explicitně deklaruje základní typ, má základní typ int.

Příklad: Příklad

enum Color : long
{
    Red,
    Green,
    Blue
}

deklaruje výčt s podkladovým typem long.

end example

Poznámka: Vývojář se může rozhodnout použít základní typ long, jako v příkladu, povolit použití hodnot, které jsou v rozsahu long , ale ne v rozsahu int, nebo zachovat tuto možnost pro budoucnost. koncová poznámka

Poznámka: C# umožňuje koncové čárky v enum_body, stejně jako to umožňuje jeden v array_initializer (§17.7). koncová poznámka

Deklarace výčtu nemůže obsahovat seznam parametrů typu, ale jakýkoli výčt vnořený uvnitř obecné deklarace třídy nebo obecná deklarace struktury je obecná deklarace výčtu, protože argumenty typu pro obsahující typ musí být zadány k vytvoření konstruovaného typu (§8.4).

19.3 Modifikátory výčtu

Volitelně může enum_declaration obsahovat posloupnost modifikátorů výčtu:

enum_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    ;

Jedná se o chybu v době kompilace, aby se stejný modifikátor zobrazoval vícekrát v deklaraci výčtu.

Modifikátory deklarace výčtu mají stejný význam jako modifikátory deklarace třídy (§15.2.2). Modifikátory abstracta a sealedstatic , však nejsou povoleny v deklaraci výčtu. Výčty nemohou být abstraktní a neumožňují odvození.

19.4 Členové výčtu

Tělo deklarace typu výčtu definuje nula nebo více členů výčtu, což jsou pojmenované konstanty typu výčtu. Žádné dva členy výčtu nemohou mít stejný název.

enum_member_declarations
    : enum_member_declaration (',' enum_member_declaration)*
    ;
enum_member_declaration
    : attributes? identifier ('=' constant_expression)?
    ;

Každý člen výčtu má přidruženou konstantní hodnotu. Typ této hodnoty je podkladovým typem pro obsahující výčt. Konstantní hodnota pro každý člen výčtu musí být v rozsahu podkladového typu výčtu.

Příklad: Příklad

enum Color: uint
{
    Red = -1,
    Green = -2,
    Blue = -3
}

výsledkem chyby v době kompilace, protože konstantní hodnoty -1, -2a -3 nejsou v rozsahu základního celočíselného typu uint.

end example

Více členů výčtu může sdílet stejnou přidruženou hodnotu.

Příklad: Příklad

enum Color
{
    Red,
    Green,
    Blue,
    Max = Blue
}

zobrazuje výčt, ve kterém mají dva členyBlue výčtu (a Max) stejnou přidruženou hodnotu.

end example

Přidružená hodnota člena výčtu je přiřazena implicitně nebo explicitně. Pokud má deklarace členu výčtu constant_expression inicializátor, hodnota tohoto konstantního výrazu implicitně převedena na základní typ výčtu, je přidružená hodnota členu výčtu. Pokud deklarace členu výčtu nemá žádný inicializátor, jeho přidružená hodnota je nastavena implicitně takto:

  • Pokud je člen výčtu prvním členem výčtu deklarovaným v typu výčtu, jeho přidružená hodnota je nula.
  • V opačném případě je přidružená hodnota členu výčtu získána zvýšením přidružené hodnoty textového předcházejícího výčtu o jeden. Tato zvýšená hodnota musí být v rozsahu hodnot, které mohou být reprezentovány základním typem, jinak dojde k chybě v době kompilace.

Příklad: Příklad

enum Color
{
    Red,
    Green = 10,
    Blue
}

class Test
{
    static void Main()
    {
        Console.WriteLine(StringFromColor(Color.Red));
        Console.WriteLine(StringFromColor(Color.Green));
        Console.WriteLine(StringFromColor(Color.Blue));
    }

    static string StringFromColor(Color c)
    {
        switch (c)
        {
            case Color.Red:
                return $"Red = {(int) c}";
            case Color.Green:
                return $"Green = {(int) c}";
            case Color.Blue:
                return $"Blue = {(int) c}";
            default:
                return "Invalid color";
      }
   }
}

vytiskne názvy členů výčtu a jejich přidružené hodnoty. Výstup je:

Red = 0
Green = 10
Blue = 11

z následujících důvodů:

  • člen Red výčtu je automaticky přiřazena nula hodnoty (protože nemá žádný inicializátor a je prvním členem výčtu);
  • člen výčtu Green je explicitně uvedena hodnota 10;
  • a člen Blue výčtu je automaticky přiřazena hodnota větší než člen, který textově předchází.

end example

Přidružená hodnota člena výčtu nesmí přímo ani nepřímo používat hodnotu vlastního přidruženého člena výčtu. Kromě tohoto omezení cykličnosti mohou inicializátory členů výčtu volně odkazovat na jiné inicializátory členů výčtu bez ohledu na jejich textovou pozici. V inicializátoru člena výčtu jsou hodnoty jiných členů výčtu vždy považovány za typ jejich základního typu, takže při odkazování na jiné členy výčtu nejsou nutné přetypování.

Příklad: Příklad

enum Circular
{
    A = B,
    B
}

výsledkem chyby v době kompilace, protože deklarace A a B jsou cyklický. A závisí na B explicitně a B závisí na A implicitně.

end example

Členy výčtu jsou pojmenovány a vymezeny způsobem přesně analogickým k polím v rámci tříd. Rozsah členu výčtu je tělo jeho obsahující typ výčtu. V rámci tohoto oboru mohou být členy výčtu odkazovány jejich jednoduchým názvem. Ze všech ostatních kódů musí být název člena výčtu kvalifikovaný s názvem jeho typu výčtu. Členové výčtu nemají deklarovanou přístupnost – člen výčtu je přístupný, pokud je jeho typ výčtu přístupný.

19.5 Typ System.Enum

Typ System.Enum je abstraktní základní třída všech typů výčtu (liší se od základního typu výčtu) a členy zděděné z System.Enum jsou k dispozici v jakémkoli typu výčtu. Převod boxingu (§10.2.9) existuje z jakéhokoliv typu výčtu na System.Enum, a přepočet rozbalení (§10.3.7) existuje od System.Enum jakéhokoli typu výčtu.

Všimněte si, že System.Enum není sám o sobě enum_type. Spíše je to class_type , ze kterého jsou odvozeny všechny enum_type. Typ System.Enum dědí z typu System.ValueType (§8.3.2), který pak dědí z typu object. Za běhu může být null hodnota typu System.Enum nebo odkaz na boxovanou hodnotu libovolného typu výčtu.

19.6 Výčtové hodnoty a operace

Každý typ výčtu definuje odlišný typ; k převodu výčtu (§10.3.3) je vyžadován převod mezi typem výčtu a integrálním typem nebo mezi dvěma typy výčtu. Sada hodnot typu výčtu je stejná jako sada hodnot základního typu a není omezena na hodnoty pojmenovaných konstant. Libovolnou hodnotu základního typu výčtu lze přetypovat na typ výčtu a je jedinečnou platnou hodnotou tohoto typu výčtu.

Členové výčtu mají typ jejich obsahující typ výčtu (s výjimkou jiných inicializátorů členů výčtu: viz §19.4). Hodnota člena výčtu deklarovaného v typu E výčtu s přidruženou hodnotou v je (E)v.

Pro hodnoty typů výčtu lze použít následující operátory:

Každý typ výčtu se automaticky odvozuje od třídy System.Enum (která je následně odvozena od System.ValueType a object). Proto lze zděděné metody a vlastnosti této třídy použít pro hodnoty typu výčtu.