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 medlemmarnaRed
,Green
ochBlue
.slutexempel
19.2 Uppräkningsdeklarationer
En uppräkningsdeklaration deklarerar en ny uppräkningstyp. En uppräkningsdeklaration börjar med nyckelordet enum
och 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 enintegral_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 intervalletlong
för men inte i intervalletint
, 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 sealed
och 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 integraltypenuint
.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
ochMax
– 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ärdet10
.- 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
ochB
är cirkulära.A
beror påB
explicit ochB
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:
==
,!=
,<
,>
,<=
,>=
(§12.12.6)- binärt
+
(§12.10.5) - binärt
-
(§12.10.6) ^
,&
,|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 och §12.9.6)sizeof
(§23.6.9)
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.
ECMA C# draft specification