Dela via


19 uppräkningar

19.1 Allmänt

En uppräkningstyp är en distinkt värdetyp (§8.3) som deklarerar en uppsättning namngivna konstanter.

Exempel: Exemplet

enum Color
{
    Red,
    Green,
    Blue
}

deklarerar en uppräkningstyp med namnet Color med medlemmarna Red, Greenoch Blue.

slutexempel

19.2 Uppräkningsdeklarationer

En uppräkningsdeklaration deklarerar en ny uppräkningstyp. En uppräkningsdeklaration börjar med nyckelordet enumoch definierar namn, tillgänglighet, underliggande typ och medlemmar i uppräkningen.

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 ',' '}'
    ;

Varje uppräkningstyp har en motsvarande integraltyp som kallas den underliggande typen av uppräkningstyp. Den här underliggande typen ska kunna representera alla uppräkningsvärden som definierats i uppräkningen. Om enum_base finns deklarerar den uttryckligen den underliggande typen. Den underliggande typen ska vara en av de integrerade typerna (§8.3.6) förutom char. Den underliggande typen kan anges antingen av en integral_type (§8.3.5) eller en integral_type_name. Löses integral_type_name på samma sätt som type_name (§7.8.1), inklusive att ta hänsyn till eventuella användningsdirektiv (§14.5).

Obs! Typen char kan inte användas som en underliggande typ, antingen med nyckelord eller via en integral_type_name. slutkommentar

En uppräkningsdeklaration som inte uttryckligen deklarerar en underliggande typ har en underliggande typ av int.

Exempel: Exemplet

enum Color : long
{
    Red,
    Green,
    Blue
}

deklarerar en uppräkning med en underliggande typ av long.

slutexempel

Obs! En utvecklare kan välja att använda en underliggande typ av long, som i exemplet, för att aktivera användning av värden som finns i intervallet long för men inte i intervallet int, eller för att bevara det här alternativet för framtiden. slutkommentar

Obs! C# tillåter ett avslutande kommatecken i en enum_body, precis som det tillåter ett i en array_initializer (§17.7). slutkommentar

En uppräkningsdeklaration får inte innehålla en typparameterlista, men ett uppräkning kapslat i en generisk klassdeklaration eller en generisk structdeklaration är en generisk uppräkningsdeklaration, eftersom typargument för den innehållande typen ska levereras för att skapa en konstruerad typ (§8.4).

19.3 Uppräkningsmodifierare

En enum_declaration kan eventuellt innehålla en sekvens med uppräkningsmodifierare:

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

Det är ett kompileringsfel för samma modifierare som visas flera gånger i en uppräkningsdeklaration.

Modifierarna för en uppräkningsdeklaration har samma betydelse som en klassdeklaration (§15.2.2). Modifierarna abstract, och sealedoch static tillåts dock inte i en uppräkningsdeklaration. Uppräkningar kan inte vara abstrakta och tillåter inte härledning.

19.4 Uppräkningsmedlemmar

Brödtexten i en uppräkningstypsdeklaration definierar noll eller fler uppräkningsmedlemmar, som är de namngivna konstanterna av uppräkningstypen. Inga två uppräkningsmedlemmar kan ha samma namn.

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

Varje uppräkningsmedlem har ett associerat konstant värde. Typen av det här värdet är den underliggande typen för den innehållande uppräkningen. Konstantvärdet för varje uppräkningsmedlem ska ligga i intervallet för den underliggande typen för uppräkningen.

Exempel: Exemplet

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

resulterar i ett kompileringsfel eftersom konstantvärdena -1, -2, och -3 inte finns i intervallet för den underliggande integraltypen uint.

slutexempel

Flera uppräkningsmedlemmar kan dela samma associerade värde.

Exempel: Exemplet

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

visar en uppräkning där två uppräkningsmedlemmar–Blue och Max– har samma associerade värde.

slutexempel

Det associerade värdet för en uppräkningsmedlem tilldelas antingen implicit eller explicit. Om deklarationen för uppräkningsmedlemmen har en constant_expression initialiserare är värdet för det konstanta uttrycket, implicit konverterat till den underliggande typen av uppräkning, det associerade värdet för uppräkningsmedlemmen. Om deklarationen för uppräkningsmedlemmen inte har någon initiering anges dess associerade värde implicit enligt följande:

  • Om uppräkningsmedlemmen är den första uppräkningsmedlemmen som deklareras i uppräkningstypen är dess associerade värde noll.
  • I annat fall erhålls det associerade värdet för uppräkningsmedlemmen genom att det associerade värdet för den text som föregår uppräkningsmedlemmen ökas med en. Detta ökade värde ska ligga inom det värdeintervall som kan representeras av den underliggande typen, annars uppstår ett kompileringsfel.

Exempel: Exemplet

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";
      }
   }
}

skriver ut uppräkningsmedlemsnamnen och deras associerade värden. Resultatet är:

Red = 0
Green = 10
Blue = 11

av följande skäl:

  • uppräkningsmedlemmen Red tilldelas automatiskt värdet noll (eftersom den inte har någon initiering och är den första uppräkningsmedlemmen);
  • uppräkningsmedlemmen Green ges uttryckligen värdet 10.
  • och uppräkningsmedlemmen Blue tilldelas automatiskt värdet ett större än den medlem som textmässigt föregår det.

slutexempel

En uppräkningsmedlems associerade värde får inte direkt eller indirekt använda värdet för sin egen associerade uppräkningsmedlem. Förutom den här cirkelbegränsningen kan uppräkningsmedlemsinitierare fritt referera till andra uppräkningsmedlemsinitierare, oavsett deras textposition. Inom en uppräkningsmedlemsinitierare behandlas värden för andra uppräkningsmedlemmar alltid som att de har den typ av underliggande typ som de har, så att avgjutningar inte är nödvändiga när de refererar till andra uppräkningsmedlemmar.

Exempel: Exemplet

enum Circular
{
    A = B,
    B
}

resulterar i ett kompileringsfel eftersom deklarationerna av A och B är cirkulära. A beror på B explicit och B beror på A implicit.

slutexempel

Uppräkningsmedlemmar namnges och omfångsbegränsas på ett sätt som exakt motsvarar fält inom klasser. Omfånget för en uppräkningsmedlem är brödtexten för dess innehållande uppräkningstyp. Inom det omfånget kan uppräkningsmedlemmar refereras till med sitt enkla namn. Från all annan kod ska namnet på en uppräkningsmedlem kvalificeras med namnet på dess uppräkningstyp. Uppräkningsmedlemmar har ingen deklarerad tillgänglighet – en uppräkningsmedlem är tillgänglig om dess innehållande uppräkningstyp är tillgänglig.

19.5 System.Enum-typen

Typen System.Enum är den abstrakta basklassen för alla uppräkningstyper (detta skiljer sig från den underliggande typen av uppräkningstyp) och de medlemmar som ärvs från System.Enum är tillgängliga i alla uppräkningstyper. En boxningskonvertering (§10.2.9) finns från alla uppräkningstyper till System.Enum, och det finns en omräkning (§10.3.7) från System.Enum till någon uppräkningstyp.

Observera att det System.Enum inte i sig är en enum_type. Det är snarare en class_type som alla enum_types härleds från. Typen System.Enum ärver från typen System.ValueType (§8.3.2), som i sin tur ärver från typen object. Vid körning kan ett värde av typen System.Enum vara null eller en referens till ett boxat värde av valfri uppräkningstyp.

19.6 Uppräkningsvärden och åtgärder

Varje uppräkningstyp definierar en distinkt typ. en explicit uppräkningskonvertering (§10.3.3) krävs för att konvertera mellan en uppräkningstyp och en integraltyp, eller mellan två uppräkningstyper. Uppsättningen med värden för uppräkningstypen är samma som uppsättningen med värden för den underliggande typen och är inte begränsad till värdena för de namngivna konstanterna. Alla värden för den underliggande typen av en uppräkning kan omvandlas till uppräkningstypen och är ett distinkt giltigt värde av den uppräkningstypen.

Uppräkningsmedlemmar har en typ av innehållande uppräkningstyp (utom inom andra uppräkningsmedlemsinitierare: se §19.4). Värdet för en uppräkningsmedlem som deklarerats i uppräkningstyp E med associerat värde v är (E)v.

Följande operatorer kan användas för värden för uppräkningstyper:

Varje uppräkningstyp härleds automatiskt från klassen System.Enum (som i sin tur härleds från System.ValueType och object). Därför kan ärvda metoder och egenskaper för den här klassen användas på värden av en uppräkningstyp.