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
členyRed
,Green
aBlue
.end example
19.2 Deklarace výčtu
Deklarace výčtu deklaruje nový typ výčtu. Deklarace výčtu začíná klíčovým slovem enum
a 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 rozsahulong
, ale ne v rozsahuint
, 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 abstract
a a sealed
static
, 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
,-2
a-3
nejsou v rozsahu základního celočíselného typuuint
.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 členy
Blue
výčtu (aMax
) 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 hodnota10
;- 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
aB
jsou cyklický.A
závisí naB
explicitně aB
závisí naA
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:
==
,!=
, ,>
<
, ,<=
(>=
§12.12.6)- binární
+
(§12.10.5) - binární
-
(§12.10.6) ^
, ,&
|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 a §12.9.6)sizeof
(§23.6.9)
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.
ECMA C# draft specification