Partager via


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 membres Red, Greenet Blue.

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é enumet 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’un integral_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, longcomme dans l’exemple, pour activer l’utilisation de valeurs qui se trouvent dans la plage, long mais pas dans la plage de int, 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 abstractmodificateurs et static sealedles 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 -1constantes , -2et -3 ne sont pas dans la plage du type uintinté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 membresBlue d’énumération ( et Max– 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 valeur 10;
  • 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. AB dépend explicitement, et B dépend A 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.Enumet 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 :

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.