Udostępnij za pośrednictwem


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łonkowskimi Red, Greeni Blue.

przykład końcowy

19.2 Deklaracje wyliczenia

Deklaracja wyliczenia deklaruje nowy typ wyliczenia. Deklaracja wyliczenia rozpoczyna się od słowa kluczowego enumi 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 longtypu , jak w przykładzie, aby włączyć użycie wartości, które znajdują się w zakresie, ale nie w zakresie long 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). abstractJednak modyfikatory , i sealednie 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, -2i -3 nie znajdują się w zakresie bazowego typu uintcał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 i Max— 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 i B są cykliczne. A zależy od B jawnie i B zależy od A 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:

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.