19 wyliczenie
19.1 Ogólne
Typ wyliczenia jest odrębnym typem wartości (§8.3), który deklaruje zestaw nazwanych stałych.
Przykład: przykład
enum Color { Red, Green, Blue }
deklaruje typ wyliczenia o nazwie
Color
z elementami członkowskimiRed
,Green
iBlue
.przykład końcowy
19.2 Deklaracje wyliczenia
Deklaracja wyliczenia deklaruje nowy typ wyliczenia. Deklaracja wyliczenia rozpoczyna się od słowa kluczowego enum
i definiuje nazwę, ułatwienia dostępu, typ bazowy i składowe wyliczenia.
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żdy typ wyliczenia ma odpowiadający typ całkowity nazywany typem bazowym typu wyliczenia. Ten typ bazowy może reprezentować wszystkie wartości modułu wyliczającego zdefiniowane w wyliczeniem. Jeśli enum_base jest obecny, jawnie deklaruje typ bazowy. Typ bazowy jest jednym z typów całkowitych (§8.3.6) innych niż char
. Typ bazowy może być określony przez element integral_type
(§8.3.5) lub integral_type_name
. Rozwiązanie integral_type_name
to zostało rozwiązane w taki sam sposób jak type_name
(§7.8.1), w tym uwzględnienie wszelkich dyrektyw stosowania (§14.5).
Uwaga:
char
typ nie może być używany jako typ bazowy , albo przez słowo kluczowe lub za pośrednictwem .integral_type_name
notatka końcowa
Deklaracja wyliczenia, która nie deklaruje jawnie typu bazowego, ma podstawowy typ int
.
Przykład: przykład
enum Color : long { Red, Green, Blue }
deklaruje wyliczenie o podstawowym typie
long
.przykład końcowy
Uwaga: deweloper może zdecydować się na użycie bazowego
long
typu , jak w przykładzie, aby włączyć użycie wartości, które znajdują się w zakresie, ale nie w zakresielong
int
, lub zachować tę opcję na przyszłość. notatka końcowa
Uwaga: język C# zezwala na końcowy przecinek w enum_body, podobnie jak w przypadku zezwalania na jeden w array_initializer (§17.7). notatka końcowa
Deklaracja wyliczenia nie może zawierać listy parametrów typu, ale każde wyliczenie zagnieżdżone wewnątrz deklaracji klasy ogólnej lub deklaracji struktury ogólnej jest deklaracją wyliczenia ogólnego, ponieważ argumenty typu zawierającego typ należy podać, aby utworzyć skonstruowany typ (§8.4).
19.3 Modyfikatory wyliczenia
Enum_declaration może opcjonalnie zawierać sekwencję modyfikatorów wyliczenia:
enum_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
;
Jest to błąd czasu kompilacji dla tego samego modyfikatora, który pojawia się wiele razy w deklaracji wyliczenia.
Modyfikatory deklaracji wyliczenia mają takie samo znaczenie jak modyfikatory deklaracji klasy (§15.2.2). abstract
Jednak modyfikatory , i sealed
nie static
są dozwolone w deklaracji wyliczenia. Wyliczenia nie mogą być abstrakcyjne i nie zezwalają na wyprowadzanie.
19.4 Składowe wyliczenia
Treść deklaracji typu wyliczenia definiuje zero lub więcej składowych wyliczenia, które są nazwane stałe typu wyliczenia. Żadna z dwóch składowych wyliczenia nie może mieć takiej samej nazwy.
enum_member_declarations
: enum_member_declaration (',' enum_member_declaration)*
;
enum_member_declaration
: attributes? identifier ('=' constant_expression)?
;
Każdy element członkowski wyliczenia ma skojarzona wartość stałą. Typ tej wartości jest typem bazowym dla wyliczenia zawierającego. Stała wartość dla każdego elementu członkowskiego wyliczenia musi być w zakresie typu bazowego dla wyliczenia.
Przykład: przykład
enum Color: uint { Red = -1, Green = -2, Blue = -3 }
powoduje błąd w czasie kompilacji, ponieważ stałe wartości
-1
,-2
i-3
nie znajdują się w zakresie bazowego typuuint
całkowitego .przykład końcowy
Wiele elementów członkowskich wyliczenia może współdzielić tę samą skojarzona wartość.
Przykład: przykład
enum Color { Red, Green, Blue, Max = Blue }
Pokazuje wyliczenie, w którym dwa elementy wyliczenia —
Blue
iMax
— mają tę samą skojarzona wartość.przykład końcowy
Skojarzona wartość elementu członkowskiego wyliczenia jest przypisywana niejawnie lub jawnie. Jeśli deklaracja składowej wyliczenia ma inicjatora constant_expression , wartość tego wyrażenia stałego, niejawnie przekonwertowana na podstawowy typ wyliczenia, jest skojarzona wartość składowej wyliczenia. Jeśli deklaracja elementu członkowskiego wyliczenia nie ma inicjatora, skojarzona z nim wartość jest ustawiana niejawnie w następujący sposób:
- Jeśli składowa wyliczenia jest pierwszym składowym wyliczenia zadeklarowany w typie wyliczenia, skojarzona z nim wartość to zero.
- W przeciwnym razie skojarzona wartość elementu członkowskiego wyliczenia jest uzyskiwana przez zwiększenie skojarzonej wartości tekstowej poprzedzającej składowej wyliczenia przez jeden. Ta zwiększona wartość mieści się w zakresie wartości, które mogą być reprezentowane przez typ bazowy, w przeciwnym razie wystąpi błąd czasu kompilacji.
Przykład: przykład
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"; } } }
Wyświetla nazwy składowych wyliczenia i skojarzone z nimi wartości. Dane wyjściowe to:
Red = 0 Green = 10 Blue = 11
z następujących powodów:
- składowa
Red
wyliczenia jest automatycznie przypisywana wartość zero (ponieważ nie ma inicjatora i jest pierwszym składowym wyliczenia);- składowa
Green
wyliczenia jest jawnie podana wartość10
;- element członkowski
Blue
wyliczenia jest automatycznie przypisywany do wartości większej niż element członkowski, który tekstowo go poprzedza.przykład końcowy
Skojarzona wartość elementu członkowskiego wyliczenia nie może być używana bezpośrednio lub pośrednio z wartością własnego skojarzonego elementu wyliczenia. Poza tym ograniczeniem cykliczności inicjatory składowych wyliczenia mogą swobodnie odnosić się do innych inicjatorów składowych wyliczenia, niezależnie od ich położenia tekstowego. W inicjatorze składowym wyliczenia wartości innych składowych wyliczenia są zawsze traktowane jako typ ich typu bazowego, dzięki czemu rzutowania nie są konieczne podczas odwoływania się do innych składowych wyliczenia.
Przykład: przykład
enum Circular { A = B, B }
powoduje błąd czasu kompilacji, ponieważ deklaracje
A
iB
są cykliczne.A
zależy odB
jawnie iB
zależy odA
niejawnie.przykład końcowy
Składowe wyliczenia są nazwane i ograniczone w sposób dokładnie analogiczny do pól w klasach. Zakres składowej wyliczenia jest treścią jego typu wyliczeniowego. W tym zakresie elementy członkowskie wyliczenia mogą być określane przy użyciu ich prostej nazwy. Ze wszystkich innych kodów nazwa składowej wyliczenia jest kwalifikowana nazwą jego typu wyliczenia. Elementy członkowskie wyliczenia nie mają żadnych zadeklarowanych ułatwień dostępu — element członkowski wyliczenia jest dostępny, jeśli jest dostępny jego typ wyliczenia.
19.5 Typ System.Enum
Typ System.Enum
jest abstrakcyjną klasą bazową wszystkich typów wyliczenia (jest to odrębne i różni się od bazowego typu wyliczenia), a składowe dziedziczone z System.Enum
są dostępne w dowolnym typie wyliczenia. Konwersja boksu (§10.2.9) istnieje z dowolnego typu wyliczenia do System.Enum
, a konwersja rozpętłania (§10.3.7) istnieje z System.Enum
do dowolnego typu wyliczenia.
Należy pamiętać, że System.Enum
nie jest to enum_type. Jest to raczej class_type , z którego pochodzą wszystkie enum_types. Typ System.Enum
dziedziczy po typie System.ValueType
(§8.3.2), który z kolei dziedziczy z typu object
. W czasie wykonywania wartość typu System.Enum
może być null
lub odwołanie do wartości pola dowolnego typu wyliczenia.
19.6 Wartości i operacje wyliczenia
Każdy typ wyliczenia definiuje odrębny typ; Jawna konwersja wyliczenia (§10.3.3) jest wymagana do konwersji między typem wyliczenia a typem całkowitym lub między dwoma typami wyliczeniowym. Zestaw wartości typu wyliczenia jest taki sam jak zestaw wartości typu bazowego i nie jest ograniczony do wartości nazwanych stałych. Dowolna wartość bazowego typu wyliczenia może być rzutowania na typ wyliczenia i jest odrębną prawidłową wartością tego typu wyliczenia.
Składowe wyliczenia mają typ zawierający typ wyliczenia (z wyjątkiem innych inicjatorów składowych wyliczenia: zobacz §19.4). Wartość elementu członkowskiego wyliczenia zadeklarowanego w typie E
wyliczenia ze skojarzona wartością v
to (E)v
.
Następujące operatory mogą być używane w wartościach typów wyliczenia:
==
, ,!=
,>
<
, ,>=
<=
(§12.12.6)- binary
+
(§12.10.5) - binary
-
(§12.10.6) ^
, ,&
|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 i §12.9.6)sizeof
(§23.6.9)
Każdy typ wyliczenia automatycznie pochodzi z klasy System.Enum
(co z kolei pochodzi od System.ValueType
i object
). W związku z tym dziedziczone metody i właściwości tej klasy mogą być używane na wartościach typu wyliczenia.
ECMA C# draft specification