Condividi tramite


19 Enumerazioni

19.1 Generale

Un tipo enum è un tipo valore distinto (§8.3) che dichiara un set di costanti denominate.

Esempio: esempio

enum Color
{
    Red,
    Green,
    Blue
}

dichiara un tipo di enumerazione denominato Color con membri Red, Greene Blue.

esempio finale

19.2 Dichiarazioni di enumerazione

Una dichiarazione enum dichiara un nuovo tipo di enumerazione. Una dichiarazione enum inizia con la parola chiave enume definisce il nome, l'accessibilità, il tipo sottostante e i membri dell'enumerazione.

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

Ogni tipo enum ha un tipo integrale corrispondente denominato tipo sottostante del tipo enumerazione. Questo tipo sottostante può rappresentare tutti i valori dell'enumeratore definiti nell'enumerazione . Se il enum_base è presente, dichiara in modo esplicito il tipo sottostante. Il tipo sottostante deve essere uno dei tipi integrali (§8.3.6) diversi da char. Il tipo sottostante può essere specificato da un integral_type oggetto (§8.3.5) o da un oggetto integral_type_name. L'oggetto integral_type_name viene risolto nello stesso modo di type_name (§7.8.1), inclusa l'assunzione di direttive using (§14.5) in considerazione.

Nota: il char tipo non può essere usato come tipo sottostante, per parola chiave o tramite un oggetto integral_type_name. nota finale

Una dichiarazione di enumerazione che non dichiara in modo esplicito un tipo sottostante ha un tipo sottostante di int.

Esempio: esempio

enum Color : long
{
    Red,
    Green,
    Blue
}

dichiara un'enumerazione con un tipo sottostante di long.

esempio finale

Nota: uno sviluppatore potrebbe scegliere di usare un tipo sottostante di long, come nell'esempio, per abilitare l'uso di valori compresi nell'intervallo di ma non nell'intervallo di long into per mantenere questa opzione per il futuro. nota finale

Nota: C# consente una virgola finale in un enum_body, proprio come se ne consenta uno in un array_initializer (§17.7). nota finale

Una dichiarazione enum non può includere un elenco di parametri di tipo, ma qualsiasi enumerazione annidata all'interno di una dichiarazione di classe generica o una dichiarazione di struct generica è una dichiarazione di enumerazione generica, poiché gli argomenti di tipo per il tipo contenitore devono essere forniti per creare un tipo costruito (§8.4).

19.3 Modificatori di enumerazione

Un enum_declaration può includere facoltativamente una sequenza di modificatori di enumerazione:

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

Si tratta di un errore in fase di compilazione per visualizzare più volte lo stesso modificatore in una dichiarazione di enumerazione.

I modificatori di una dichiarazione di enumerazione hanno lo stesso significato di quelli di una dichiarazione di classe (§15.2.2). Tuttavia, i abstractmodificatori , e e static non sono consentiti in una dichiarazione di sealedenumerazione. Le enumerazioni non possono essere astratte e non consentono la derivazione.

19.4 Membri Enumerazione

Il corpo di una dichiarazione di tipo enum definisce zero o più membri enumerazione, ovvero le costanti denominate del tipo enum. Nessun membro di enumerazione può avere lo stesso nome.

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

Ogni membro enum ha un valore costante associato. Il tipo di questo valore è il tipo sottostante per l'enumerazione contenitore. Il valore costante per ogni membro enumerazione deve essere compreso nell'intervallo del tipo sottostante per l'enumerazione.

Esempio: esempio

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

restituisce un errore in fase di compilazione perché i valori -1costanti , -2e -3 non si trovano nell'intervallo del tipo uintintegrale sottostante.

esempio finale

Più membri enumerazione possono condividere lo stesso valore associato.

Esempio: esempio

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

mostra un'enumerazione in cui due membri enumerazione,Blue e Max, hanno lo stesso valore associato.

esempio finale

Il valore associato di un membro enumerazione viene assegnato in modo implicito o esplicito. Se la dichiarazione del membro enumerazione ha un inizializzatore constant_expression , il valore di tale espressione costante, convertito in modo implicito nel tipo sottostante dell'enumerazione, è il valore associato del membro enumerazione. Se la dichiarazione del membro enumerazione non dispone di inizializzatore, il valore associato viene impostato in modo implicito, come indicato di seguito:

  • Se il membro enum è il primo membro enumerazione dichiarato nel tipo enumerazione, il valore associato è zero.
  • In caso contrario, il valore associato del membro enumerazione viene ottenuto aumentando di uno il valore associato del membro enumerazione precedente al testo. Questo valore aumentato deve essere compreso nell'intervallo di valori che possono essere rappresentati dal tipo sottostante. In caso contrario, si verifica un errore in fase di compilazione.

Esempio: esempio

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

stampa i nomi dei membri enumerazione e i relativi valori associati. L'output è il seguente:

Red = 0
Green = 10
Blue = 11

per i motivi seguenti:

  • al membro Red enumerazione viene assegnato automaticamente il valore zero (poiché non ha inizializzatore ed è il primo membro enumerazione);
  • al membro Green enumerazione viene assegnato in modo esplicito il valore 10;
  • e al membro Blue enumerazione viene assegnato automaticamente il valore uno maggiore del membro che lo precede a livello di testo.

esempio finale

Il valore associato di un membro di enumerazione non deve, direttamente o indirettamente, utilizzare il valore del proprio membro enumerazione associato. Oltre a questa restrizione di circolarità, gli inizializzatori di membri enumerazione possono fare liberamente riferimento ad altri inizializzatori di membri enumerazione, indipendentemente dalla loro posizione testuale. All'interno di un inizializzatore membro enumerazione, i valori di altri membri enumerazione vengono sempre considerati come con il tipo del tipo sottostante, in modo che i cast non siano necessari quando si fa riferimento ad altri membri enumerazione.

Esempio: esempio

enum Circular
{
    A = B,
    B
}

genera un errore in fase di compilazione perché le dichiarazioni di A e B sono circolari. AB dipende in modo esplicito e B dipende in A modo implicito.

esempio finale

I membri enumerazione vengono denominati e con ambito in modo esattamente analogo ai campi all'interno delle classi. L'ambito di un membro enumerazione è il corpo del relativo tipo di enumerazione contenitore. All'interno di tale ambito, i membri enumerazione possono essere indicati con il nome semplice. Da tutto il codice, il nome di un membro enumerazione deve essere qualificato con il nome del relativo tipo di enumerazione. I membri dell'enumerazione non dispongono di accessibilità dichiarata. Un membro enum è accessibile se il tipo di enumerazione che lo contiene è accessibile.

19.5 Tipo System.Enum

Il tipo System.Enum è la classe base astratta di tutti i tipi di enumerazione (questo è distinto e diverso dal tipo sottostante del tipo enum) e i membri ereditati da System.Enum sono disponibili in qualsiasi tipo di enumerazione. Esiste una conversione boxing (§10.2.9) da qualsiasi tipo di enumerazione a System.Enume una conversione unboxing (§10.3.7) esiste da System.Enum a qualsiasi tipo di enumerazione.

Si noti che System.Enum non è un enum_type. È invece un class_type da cui derivano tutti i enum_type. Il tipo eredita dal tipo System.Enum (§8.3.2), che a sua volta eredita dal tipo object.System.ValueType In fase di esecuzione, un valore di tipo System.Enum può essere null o un riferimento a un valore boxed di qualsiasi tipo enumerazione.

19.6 Valori e operazioni di enumerazione

Ogni tipo di enumerazione definisce un tipo distinto; È necessaria una conversione esplicita dell'enumerazione (§10.3.3) per eseguire la conversione tra un tipo enum e un tipo integrale o tra due tipi enum. Il set di valori del tipo enumerazione è uguale al set di valori del tipo sottostante e non è limitato ai valori delle costanti denominate. Qualsiasi valore del tipo sottostante di un'enumerazione può essere eseguito il cast al tipo enumerazione ed è un valore valido distinto di tale tipo di enumerazione.

I membri enumerazione hanno il tipo di tipo enumerazione contenente (ad eccezione di altri inizializzatori di membri enumerazione: vedere §19.4). Il valore di un membro enum dichiarato nel tipo E enum con valore v associato è (E)v.

Gli operatori seguenti possono essere usati sui valori dei tipi di enumerazione:

Ogni tipo di enumerazione deriva automaticamente dalla classe System.Enum ( che a sua volta deriva da System.ValueType e object). Pertanto, i metodi e le proprietà ereditati di questa classe possono essere usati sui valori di un tipo enumerazione.