19 Enumerationen
19.1 Allgemein
Ein Enumerationstyp ist ein eindeutiger Werttyp (§8.3), der einen Satz benannter Konstanten deklariert.
Beispiel: Das Beispiel
enum Color { Red, Green, Blue }
deklariert einen Enumerationstyp,
Color
der mit MembernRed
,Green
undBlue
.Endbeispiel
19.2 Enumerationsdeklarationen
Eine Enumerationsdeklaration deklariert einen neuen Enumerationstyp. Eine Enumerationsdeklaration beginnt mit dem Schlüsselwort enum
und definiert den Namen, die Barrierefreiheit, den zugrunde liegenden Typ und die Member der Enumeration.
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 ',' '}'
;
Jeder Enumerationstyp weist einen entsprechenden integralen Typ auf, der als zugrunde liegender Typ des Enumerationstyps bezeichnet wird. Dieser zugrunde liegende Typ muss alle in der Enumeration definierten Enumerationswerte darstellen können. Wenn die enum_base vorhanden ist, deklariert sie explizit den zugrunde liegenden Typ. Der zugrunde liegende Typ muss eine der anderen integralen Typen (§8.3.6) sein als char
. Der zugrunde liegende Typ kann entweder durch ein integral_type
(§8.3.5) oder ein integral_type_name
. Die integral_type_name
Lösung erfolgt auf die gleiche Weise wie type_name
(§7.8.1), einschließlich der Verwendungsrichtlinien (§14.5).
Hinweis: Der
char
Typ kann nicht als zugrunde liegender Typ verwendet werden, entweder nach Schlüsselwort oder über einintegral_type_name
. Endnote
Eine Enumerationsdeklaration, die keinen zugrunde liegenden Typ explizit deklariert, weist einen zugrunde liegenden Typ auf int
.
Beispiel: Das Beispiel
enum Color : long { Red, Green, Blue }
deklariert eine Enumeration mit einem zugrunde liegenden Typ von
long
.Endbeispiel
Hinweis: Ein Entwickler kann einen zugrunde liegenden Typ von
long
, wie im Beispiel, verwenden, um die Verwendung von Werten zu ermöglichen, die sich im Bereich befindenlong
, aber nicht im Bereich vonint
, oder um diese Option für die Zukunft beizubehalten. Endnote
Hinweis: C# ermöglicht ein nachfolgendes Komma in einem enum_body, genau wie in einem array_initializer (§17.7). Endnote
Eine Enumerationsdeklaration kann keine Typparameterliste enthalten, aber jede in einer generischen Klassendeklaration oder einer generischen Strukturdeklaration geschachtelte Enumeration ist eine generische Enumerationsdeklaration, da Typargumente für den enthaltenden Typ angegeben werden müssen, um einen konstruierten Typ (§8.4) zu erstellen.
19.3 Enumerationsmodifizierer
Ein enum_declaration kann optional eine Sequenz von Enumerationsmodifizierern enthalten:
enum_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
;
Es handelt sich um einen Kompilierungszeitfehler für denselben Modifizierer, der in einer Enumerationsdeklaration mehrmals angezeigt wird.
Die Modifizierer einer Enumerationsdeklaration haben dieselbe Bedeutung wie die einer Klassendeklaration (§15.2.2). Die abstract
Modifizierer und , und sealed
static
Modifizierer sind jedoch in einer Enumerationsdeklaration nicht zulässig. Enumerationen können nicht abstrahiert werden und dürfen keine Ableitung zulassen.
19.4 Enumerationsmitglieder
Der Textkörper einer Enumerationstypdeklaration definiert null oder mehr Enumerationsmember, die die benannten Konstanten des Enumerationstyps sind. Keine zwei Enumerationselemente können denselben Namen haben.
enum_member_declarations
: enum_member_declaration (',' enum_member_declaration)*
;
enum_member_declaration
: attributes? identifier ('=' constant_expression)?
;
Jedes Enumerationselement weist einen zugeordneten Konstantenwert auf. Der Typ dieses Werts ist der zugrunde liegende Typ für die enthaltende Enumeration. Der konstante Wert für jedes Enumerationselement muss sich im Bereich des zugrunde liegenden Typs für die Enumeration befinden.
Beispiel: Das Beispiel
enum Color: uint { Red = -1, Green = -2, Blue = -3 }
führt zu einem Kompilierungsfehler, da sich die Konstantenwerte
-1
-2
und-3
nicht im Bereich des zugrunde liegenden integralen Typsuint
befinden.Endbeispiel
Mehrere Enumerationselemente können denselben zugeordneten Wert gemeinsam nutzen.
Beispiel: Das Beispiel
enum Color { Red, Green, Blue, Max = Blue }
zeigt eine Enumeration an, in der zwei Enumerationselemente –
Blue
undMax
– denselben zugeordneten Wert aufweisen.Endbeispiel
Der zugeordnete Wert eines Enumerationselements wird entweder implizit oder explizit zugewiesen. Wenn die Deklaration des Enumerationselements über einen constant_expression Initialisierer verfügt, ist der Wert dieses Konstantenausdrucks, der implizit in den zugrunde liegenden Typ der Enumeration konvertiert wird, der zugeordnete Wert des Enumerationselements. Wenn die Deklaration des Enumerationselements keinen Initialisierer aufweist, wird der zugehörige Wert implizit wie folgt festgelegt:
- Wenn das Enumerationselement das erste Enumerationselement ist, das im Enumerationstyp deklariert ist, ist der zugehörige Wert null.
- Andernfalls wird der zugeordnete Wert des Enumerationselements abgerufen, indem der zugeordnete Wert des textual vorangehenden Enumerationselements um eins erhöht wird. Dieser erhöhte Wert liegt innerhalb des Wertebereichs, der durch den zugrunde liegenden Typ dargestellt werden kann, andernfalls tritt ein Kompilierungszeitfehler auf.
Beispiel: Das Beispiel
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"; } } }
druckt die Enumerationsmememmnamen und die zugehörigen Werte aus. Die Ausgabe lautet:
Red = 0 Green = 10 Blue = 11
aus folgenden Gründen:
- dem Enumerationselement wird automatisch der Wert Null zugewiesen (da er keinen Initialisierer hat und das erste Enumerationselement
Red
ist);- das Enumerationselement
Green
explizit den Wert10
erhält;- und dem Enumerationselement
Blue
wird automatisch der Wert 1 zugewiesen, der größer als das Element ist, dem textlich vorausgeht.Endbeispiel
Der zugehörige Wert eines Enumerationsmitglieds darf nicht direkt oder indirekt den Wert eines eigenen zugeordneten Enumerationselements verwenden. Abgesehen von dieser Zirkelitätseinschränkung können Enum-Memberinitialisierer frei auf andere Enumerationsmemtialisierer verweisen, unabhängig von ihrer Textposition. Innerhalb eines Enumerationsmemberinitializers werden Werte anderer Enumerationsmember immer mit dem Typ ihres zugrunde liegenden Typs behandelt, sodass Umwandlungen beim Verweisen auf andere Enumerationsmember nicht erforderlich sind.
Beispiel: Das Beispiel
enum Circular { A = B, B }
führt zu einem Kompilierungsfehler, da die Deklarationen von
A
undB
sind zirkulär.A
hängt vonB
explizit ab undB
hängt implizit davon abA
.Endbeispiel
Enumerationsmember werden genau analog zu Feldern innerhalb von Klassen benannt und bereichsorientiert. Der Bereich eines Enumerationselements ist der Textkörper des enthaltenden Enumerationstyps. Innerhalb dieses Bereichs können Enumerationselemente anhand ihres einfachen Namens bezeichnet werden. Aus allen anderen Code wird der Name eines Enumerationselements mit dem Namen seines Enumerationstyps qualifiziert. Enumerationsmember verfügen nicht über deklarierte Barrierefreiheit . Auf ein Enumerationselement kann zugegriffen werden, wenn auf den enum-Typ zugegriffen werden kann.
19.5 Der System.Enum-Typ
Der Typ System.Enum
ist die abstrakte Basisklasse aller Enumerationstypen (dies unterscheidet sich von dem zugrunde liegenden Typ des Enumerationstyps), und die geerbten System.Enum
Member sind in jedem Enumerationstyp verfügbar. Eine Boxumwandlung (§10.2.9) besteht aus einem beliebigen Enumerationstyp in System.Enum
, und eine Unboxing-Konvertierung (§10.3.7) ist von System.Enum
einem beliebigen Enumerationstyp aus vorhanden.
Beachten Sie, dass System.Enum
es sich nicht selbst um eine enum_type handelt. Vielmehr handelt es sich um eine class_type , von der alle enum_typeabgeleitet werden. Der Typ System.Enum
erbt vom Typ System.ValueType
(§8.3.2), der wiederum vom Typ object
erbt. Zur Laufzeit kann ein Wert vom Typ System.Enum
oder ein Bezug auf einen Boxwert eines beliebigen Enumerationstyps sein null
.
19.6 Enumerationswerte und -vorgänge
Jeder Enumerationstyp definiert einen unterschiedlichen Typ; Eine explizite Enumerationskonvertierung (§10.3.3) ist erforderlich, um zwischen einem Enumerationstyp und einem integralen Typ oder zwischen zwei Enumerationstypen zu konvertieren. Der Wertesatz des Enumerationstyps entspricht dem Wertesatz des zugrunde liegenden Typs und ist nicht auf die Werte der benannten Konstanten beschränkt. Jeder Wert des zugrunde liegenden Typs einer Enumeration kann in den Enumerationstyp umwandeln und ist ein eindeutiger gültiger Wert dieses Enumerationstyps.
Enumerationsmember haben den Typ ihres enthaltenden Enumerationstyps (außer in anderen Enumerationsminitialisierern: siehe §19.4). Der Wert eines Enumerationselements, das im Enumerationstyp E
mit dem zugeordneten Wert v
deklariert ist (E)v
.
Die folgenden Operatoren können für Werte von Enumerationstypen verwendet werden:
==
,!=
,<
,>
,<=
,>=
(§12.12.6)- binär
+
(§12.10.5) - binär
-
(§12.10.6) ^
,&
|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 und §12.9.6)sizeof
(§23.6.9)
Jeder Enumerationstyp wird automatisch von der Klasse System.Enum
abgeleitet (die wiederum von System.ValueType
und object
) abgeleitet wird. Daher können geerbte Methoden und Eigenschaften dieser Klasse für Werte eines Enumerationstyps verwendet werden.
ECMA C# draft specification