Condividi tramite


Tipi di enumerazione (riferimenti per C#)

Un tipo di enumerazione (o tipo enum) è un tipo valore definito da un set di costanti denominate del tipo numerico integrale sottostante . Per definire un tipo di enumerazione, usare la enum parola chiave e specificare i nomi dei membri dell'enumerazione:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

Per impostazione predefinita, i valori costanti associati dei membri dell'enumerazione sono di tipo int; iniziano con zero e aumentano di uno in base all'ordine testuale della definizione. È possibile specificare in modo esplicito qualsiasi altro tipo numerico integrale come tipo sottostante di un tipo di enumerazione. È anche possibile specificare in modo esplicito i valori costanti associati, come illustrato nell'esempio seguente:

enum ErrorCode : ushort
{
    None = 0,
    Unknown = 1,
    ConnectionLost = 100,
    OutlierReading = 200
}

Non è possibile definire un metodo all'interno della definizione di un tipo di enumerazione. Per aggiungere funzionalità a un tipo di enumerazione, creare un membro di estensione.

Il valore predefinito di un tipo E di enumerazione è il valore prodotto dall'espressione (E)0, anche se zero non ha il membro enumerazione corrispondente.

Conversioni implicite da zero

C# consente conversioni implicite dal valore 0 letterale a qualsiasi tipo di enumerazione e dai const valori uguali a zero. Questo comportamento può causare risultati imprevisti quando un'enumerazione non include un membro con il valore zero:

public enum GpioPort
{
    GpioA = 1,
    GpioB,
    GpioC,
    GpioD
}

public class ZeroConversionExample
{
    public static void Main()
    {
        // This compiles without warning but creates an invalid enum value
        GpioPort port1 = (GpioPort)0;
        Console.WriteLine($"port1: {port1}"); // Output: port1: 0

        // This also compiles due to implicit conversion from zero
        GpioPort port2 = GetPort(0);
        Console.WriteLine($"port2: {port2}"); // Output: port2: 0

        // Check if the enum value is valid
        bool isValid1 = Enum.IsDefined(typeof(GpioPort), port1);
        bool isValid2 = Enum.IsDefined(typeof(GpioPort), port2);
        Console.WriteLine($"port1 is valid: {isValid1}"); // Output: port1 is valid: False
        Console.WriteLine($"port2 is valid: {isValid2}"); // Output: port2 is valid: False

        // Safer approach - validate enum values
        if (Enum.IsDefined(typeof(GpioPort), 0))
        {
            GpioPort safePort = (GpioPort)0;
        }
        else
        {
            Console.WriteLine("Value 0 is not a valid GpioPort");
            // Handle the invalid case appropriately
        }
    }

    public static GpioPort GetPort(GpioPort port)
    {
        return port;
    }
}

Nell'esempio precedente viene assegnato sia port1 che port2 al valore 0, ma GpioPort non ha alcun membro con tale valore. Il Enum.IsDefined metodo conferma che questi valori non sono validi per l'enumerazione.

Questa conversione implicita esiste perché il modello a 0 bit è l'impostazione predefinita per tutti i tipi di struct, inclusi tutti i tipi di enumerazione. Tuttavia, può introdurre bug nel codice. Per evitare questi problemi:

  • È consigliabile definire quasi sempre un membro con valore 0 nelle enumerazioni.
  • Usare Enum.IsDefined per convalidare i valori di enumerazione durante la conversione da tipi numerici.
  • Prestare attenzione quando si usano parametri numerici che potrebbero essere convertiti in modo implicito in tipi enumerazione.

Si usa un tipo di enumerazione per rappresentare una scelta tra un set di valori che si escludono a vicenda o una combinazione di scelte. Per rappresentare una combinazione di scelte, definisci un tipo di enumerazione come flag di bit.

Tipi di enumerazione come flag dei bit

Se si desidera che un tipo di enumerazione rappresenti una combinazione di scelte, definire i membri dell'enumerazione per tali scelte in modo tale che ogni singola scelta sia rappresentata come un campo di bit. Ovvero, i valori associati di tali membri dell'enumerazione devono essere potenze di due. Quindi, è possibile usare gli operatori | logici bit per bit o & per combinare le scelte o intersecare le combinazioni di scelte, rispettivamente. Per indicare che un tipo di enumerazione dichiara i campi di bit, applicare l'attributo Flags . Come illustrato nell'esempio seguente, è anche possibile includere alcune combinazioni tipiche nella definizione di un tipo di enumerazione.

[Flags]
public enum Days
{
    None      = 0b_0000_0000,  // 0
    Monday    = 0b_0000_0001,  // 1
    Tuesday   = 0b_0000_0010,  // 2
    Wednesday = 0b_0000_0100,  // 4
    Thursday  = 0b_0000_1000,  // 8
    Friday    = 0b_0001_0000,  // 16
    Saturday  = 0b_0010_0000,  // 32
    Sunday    = 0b_0100_0000,  // 64
    Weekend   = Saturday | Sunday
}

public class FlagsEnumExample
{
    public static void Main()
    {
        Days meetingDays = Days.Monday | Days.Wednesday | Days.Friday;
        Console.WriteLine(meetingDays);
        // Output:
        // Monday, Wednesday, Friday

        Days workingFromHomeDays = Days.Thursday | Days.Friday;
        Console.WriteLine($"Join a meeting by phone on {meetingDays & workingFromHomeDays}");
        // Output:
        // Join a meeting by phone on Friday

        bool isMeetingOnTuesday = (meetingDays & Days.Tuesday) == Days.Tuesday;
        Console.WriteLine($"Is there a meeting on Tuesday: {isMeetingOnTuesday}");
        // Output:
        // Is there a meeting on Tuesday: False

        var a = (Days)37;
        Console.WriteLine(a);
        // Output:
        // Monday, Wednesday, Saturday
    }
}

Per altre informazioni ed esempi, vedere la pagina di riferimento dell'API System.FlagsAttribute e i membri non esclusivi e la sezione Attributi Flags della pagina di riferimento dell'API System.Enum .

Il tipo System.Enum e il vincolo enum

Il System.Enum tipo è la classe base astratta di tutti i tipi di enumerazione. Fornisce diversi metodi per ottenere informazioni su un tipo di enumerazione e i relativi valori. Per altre informazioni ed esempi, vedere la pagina di riferimento dell'API System.Enum .

È possibile usare System.Enum in un vincolo di classe base (noto come vincolo enum) per specificare che un parametro di tipo è un tipo di enumerazione. Qualsiasi tipo di enumerazione soddisfa anche il struct vincolo , che viene usato per specificare che un parametro di tipo è un tipo di valore non nullable.

Conversioni

Per qualsiasi tipo di enumerazione, esistono conversioni esplicite tra il tipo di enumerazione e il tipo integrale sottostante. Se si converte un valore di enumerazione al tipo sottostante, il risultato è il valore intero associato del membro di enumerazione.

public enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

public class EnumConversionExample
{
    public static void Main()
    {
        Season a = Season.Autumn;
        Console.WriteLine($"Integral value of {a} is {(int)a}");  // output: Integral value of Autumn is 2

        var b = (Season)1;
        Console.WriteLine(b);  // output: Summer

        var c = (Season)4;
        Console.WriteLine(c);  // output: 4
    }
}

Utilizzare il metodo Enum.IsDefined per determinare se un tipo di enumerazione contiene un membro enum con lo specifico valore associato.

Per qualsiasi tipo di enumerazione, esistono conversioni di boxing e unboxing rispettivamente verso e dal tipo System.Enum.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Vedere anche