19 énumérations
19.1 Général
Un type d’énumération est un type valeur distinct (§8.3) qui déclare un ensemble de constantes nommées.
Exemple : l’exemple
enum Color { Red, Green, Blue }
déclare un type d’énumération nommé
Color
avec des membresRed
,Green
etBlue
.exemple de fin
19.2 Déclarations d’énumération
Une déclaration d’énumération déclare un nouveau type d’énumération. Une déclaration d’énumération commence par le mot clé enum
et définit le nom, l’accessibilité, le type sous-jacent et les membres de l’énumération.
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 ',' '}'
;
Chaque type d’énumération a un type intégral correspondant appelé le type sous-jacent du type d’énumération. Ce type sous-jacent peut représenter toutes les valeurs d’énumérateur définies dans l’énumération. Si le enum_base est présent, il déclare explicitement le type sous-jacent. Le type sous-jacent doit être l’un des types intégraux (§8.3.6) autres que char
. Le type sous-jacent peut être spécifié par un integral_type
(§8.3.5) ou un integral_type_name
. Il integral_type_name
est résolu de la même façon que type_name
(§7.8.1), y compris en tenant compte des directives d’utilisation (§14.5).
Remarque : Le
char
type ne peut pas être utilisé comme type sous-jacent, par mot clé ou par le biais d’unintegral_type_name
. Note de fin
Une déclaration d’énumération qui ne déclare pas explicitement un type sous-jacent a un type sous-jacent .int
Exemple : l’exemple
enum Color : long { Red, Green, Blue }
déclare une énumération avec un type sous-jacent de
long
.exemple de fin
Remarque : un développeur peut choisir d’utiliser un type sous-jacent,
long
comme dans l’exemple, pour activer l’utilisation de valeurs qui se trouvent dans la plage,long
mais pas dans la plage deint
, ou pour conserver cette option pour l’avenir. Note de fin
Remarque : C# autorise une virgule de fin dans un enum_body, tout comme elle en autorise une dans un array_initializer (§17.7). Note de fin
Une déclaration d’énumération ne peut pas inclure une liste de paramètres de type, mais toute énumération imbriquée dans une déclaration de classe générique ou une déclaration de struct générique est une déclaration d’énumération générique, car les arguments de type pour le type conteneur doivent être fournis pour créer un type construit (§8.4).
19.3 Modificateurs d’énumération
Une enum_declaration peut éventuellement inclure une séquence de modificateurs d’énumération :
enum_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
;
Il s’agit d’une erreur au moment de la compilation pour que le même modificateur apparaisse plusieurs fois dans une déclaration d’énumération.
Les modificateurs d’une déclaration d’énumération ont la même signification que ceux d’une déclaration de classe (§15.2.2). Toutefois, les abstract
modificateurs et static
sealed
les modificateurs ne sont pas autorisés dans une déclaration d’énumération. Les énumérations ne peuvent pas être abstraites et ne permettent pas la dérivation.
19.4 Membres enum
Le corps d’une déclaration de type enum définit zéro ou plusieurs membres d’énumération, qui sont les constantes nommées du type d’énumération. Aucun membre d’énumération ne peut avoir le même nom.
enum_member_declarations
: enum_member_declaration (',' enum_member_declaration)*
;
enum_member_declaration
: attributes? identifier ('=' constant_expression)?
;
Chaque membre d’énumération a une valeur constante associée. Le type de cette valeur est le type sous-jacent de l’énumération conteneur. La valeur constante de chaque membre d’énumération doit se trouver dans la plage du type sous-jacent de l’énumération.
Exemple : l’exemple
enum Color: uint { Red = -1, Green = -2, Blue = -3 }
entraîne une erreur au moment de la compilation, car les valeurs
-1
constantes ,-2
et-3
ne sont pas dans la plage du typeuint
intégral sous-jacent .exemple de fin
Plusieurs membres d’énumération peuvent partager la même valeur associée.
Exemple : l’exemple
enum Color { Red, Green, Blue, Max = Blue }
affiche une énumération dans laquelle deux membres
Blue
d’énumération ( etMax
– ont la même valeur associée.exemple de fin
La valeur associée d’un membre d’énumération est affectée implicitement ou explicitement. Si la déclaration du membre d’énumération a un initialiseur constant_expression , la valeur de cette expression constante, implicitement convertie en type sous-jacent de l’énumération, est la valeur associée du membre d’énumération. Si la déclaration du membre d’énumération n’a pas d’initialiseur, sa valeur associée est définie implicitement, comme suit :
- Si le membre d’énumération est le premier membre d’énumération déclaré dans le type d’énumération, sa valeur associée est égale à zéro.
- Dans le cas contraire, la valeur associée du membre d’énumération est obtenue en augmentant la valeur associée du membre d’énumération précédent par un. Cette valeur accrue doit se trouver dans la plage de valeurs qui peuvent être représentées par le type sous-jacent, sinon une erreur au moment de la compilation se produit.
Exemple : l’exemple
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"; } } }
imprime les noms des membres d’énumération et leurs valeurs associées. La sortie est la suivante :
Red = 0 Green = 10 Blue = 11
pour les raisons suivantes :
- le membre
Red
d’énumération est automatiquement affecté à la valeur zéro (car il n’a pas d’initialiseur et est le premier membre d’énumération) ;- le membre
Green
enum est explicitement donné la valeur10
;- et le membre
Blue
d’énumération est automatiquement affecté à la valeur supérieure au membre qui précède textuellement celui-ci.exemple de fin
La valeur associée d’un membre d’énumération ne doit pas, directement ou indirectement, utiliser la valeur de son propre membre d’énumération associé. À part cette restriction de circularité, les initialiseurs membres d’énumération peuvent librement faire référence à d’autres initialiseurs de membres d’énumération, quelle que soit leur position textuelle. Dans un initialiseur de membre d’énumération, les valeurs d’autres membres d’énumération sont toujours traitées comme ayant le type de leur type sous-jacent, afin que les casts ne soient pas nécessaires lors de la référence à d’autres membres d’énumération.
Exemple : l’exemple
enum Circular { A = B, B }
entraîne une erreur au moment de la compilation, car les déclarations et
A
B
sont circulaires.A
B
dépend explicitement, etB
dépendA
implicitement.exemple de fin
Les membres d’énumération sont nommés et délimités d’une manière exactement analogue aux champs dans les classes. L’étendue d’un membre d’énumération est le corps de son type d’énumération contenant. Dans cette étendue, les membres d’énumération peuvent être référencés par leur nom simple. À partir de tous les autres codes, le nom d’un membre d’énumération doit être qualifié avec le nom de son type d’énumération. Les membres d’énumération n’ont pas d’accessibilité déclarée : un membre d’énumération est accessible si son type d’énumération contenant est accessible.
19.5 Type System.Enum
Le type System.Enum
est la classe de base abstraite de tous les types d’énumération (il s’agit d’un type distinct et différent du type sous-jacent de l’énumération), et les membres hérités System.Enum
sont disponibles dans n’importe quel type d’énumération. Une conversion de boxe (§10.2.9) existe à partir de n’importe quel type d’énumération en System.Enum
et une conversion d’unboxing (§10.3.7) existe depuis System.Enum
n’importe quel type d’énumération.
Notez que System.Enum
ce n’est pas lui-même un enum_type. Il s’agit plutôt d’une class_type à partir de laquelle tous les enum_typesont dérivés. Le type System.Enum
hérite du type System.ValueType
(§8.3.2), qui hérite à son tour du type object
. Au moment de l’exécution, une valeur de type System.Enum
peut être null
ou une référence à une valeur boxed de n’importe quel type d’énumération.
19.6 Valeurs et opérations d’énumération
Chaque type d’énumération définit un type distinct ; une conversion d’énumération explicite (§10.3.3) est nécessaire pour effectuer une conversion entre un type d’énumération et un type intégral, ou entre deux types d’énumération. L’ensemble de valeurs du type d’énumération est identique au jeu de valeurs du type sous-jacent et n’est pas limité aux valeurs des constantes nommées. Toute valeur du type sous-jacent d’une énumération peut être convertie en type d’énumération et est une valeur valide distincte de ce type d’énumération.
Les membres enum ont le type de leur type d’énumération contenant (sauf dans d’autres initialiseurs de membres d’énumération : voir §19.4). La valeur d’un membre d’énumération déclaré dans le type E
d’énumération avec la valeur v
associée est (E)v
.
Les opérateurs suivants peuvent être utilisés sur les valeurs des types d’énumération :
==
,!=
,<
>
, ,<=
>=
(§12.12.6)- binary
+
(§12.10.5) - binary
-
(§12.10.6) ^
, ,&
|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 et §12.9.6)sizeof
(§23.6.9)
Chaque type d’énumération dérive automatiquement de la classe System.Enum
(qui, à son tour, dérive de System.ValueType
et object
). Ainsi, les méthodes héritées et les propriétés de cette classe peuvent être utilisées sur les valeurs d’un type d’énumération.
ECMA C# draft specification