Classe System.Enum

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

Un'enumerazione è un set di costanti denominate il cui tipo sottostante è qualsiasi tipo integrale. Se non viene dichiarato in modo esplicito alcun tipo sottostante, Int32 viene utilizzato . Enum è la classe base per tutte le enumerazioni in .NET. I tipi di enumerazione sono definiti dalla enum parola chiave in C#, dal Enumcostrutto ...End Enum in Visual Basic e dalla type parola chiave in F#.

Enum fornisce metodi per confrontare le istanze di questa classe, convertendo il valore di un'istanza nella relativa rappresentazione di stringa, convertendo la rappresentazione di stringa di un numero in un'istanza di questa classe e creando un'istanza di un'enumerazione e un valore specificati.

È anche possibile considerare un'enumerazione come un campo di bit. Per altre informazioni, vedere la sezione Membri non esclusivi e l'attributo Flags e FlagsAttribute.

Creare un tipo di enumerazione

I linguaggi di programmazione in genere forniscono la sintassi per dichiarare un'enumerazione costituita da un set di costanti denominate e i relativi valori. Nell'esempio seguente viene illustrata la sintassi usata da C#, F# e Visual Basic per definire un'enumerazione. Crea un'enumerazione denominata ArrivalStatus con tre membri: ArrivalStatus.Early, ArrivalStatus.OnTimee ArrivalStatus.Late. Si noti che in tutti i casi, l'enumerazione non eredita in modo esplicito da Enum. La relazione di ereditarietà viene gestita in modo implicito dal compilatore.

public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 };
type ArrivalStatus =
    | Late = -1
    | OnTime = 0
    | Early = 1
Public Enum ArrivalStatus1 As Integer
    Late = -1
    OnTime = 0
    Early = 1
End Enum

Avviso

Non è mai necessario creare un tipo di enumerazione il cui tipo sottostante è non integrale o Char. Sebbene sia possibile creare un tipo di enumerazione di questo tipo tramite reflection, le chiamate al metodo che utilizzano il tipo risultante non sono affidabili e possono anche generare eccezioni aggiuntive.

Creare un'istanza di un tipo di enumerazione

È possibile creare un'istanza di un tipo di enumerazione esattamente come si crea un'istanza di qualsiasi altro tipo di valore: dichiarando una variabile e assegnando una delle costanti dell'enumerazione. Nell'esempio seguente viene creata un'istanza di un oggetto ArrivalStatus il cui valore è ArrivalStatus.OnTime.

public class Example
{
   public static void Main()
   {
      ArrivalStatus status = ArrivalStatus.OnTime;
      Console.WriteLine("Arrival Status: {0} ({0:D})", status);
   }
}
// The example displays the following output:
//       Arrival Status: OnTime (0)
let status = ArrivalStatus.OnTime
printfn $"Arrival Status: {status} ({status:D})"
// The example displays the following output:
//       Arrival Status: OnTime (0)
Public Module Example1
    Public Sub Main()
        Dim status As ArrivalStatus1 = ArrivalStatus1.OnTime
        Console.WriteLine("Arrival Status: {0} ({0:D})", status)
    End Sub
End Module
' The example displays the following output:
'        Arrival Status: OnTime (0)

È anche possibile creare un'istanza di un valore di enumerazione nei modi seguenti:

  • Usando le funzionalità di un particolare linguaggio di programmazione per eseguire il cast (come in C#) o convertire (come in Visual Basic) un valore intero in un valore di enumerazione. Nell'esempio seguente viene creato un ArrivalStatus oggetto il cui valore è ArrivalStatus.Early in questo modo.

    ArrivalStatus status2 = (ArrivalStatus)1;
    Console.WriteLine("Arrival Status: {0} ({0:D})", status2);
    // The example displays the following output:
    //       Arrival Status: Early (1)
    
    let status2 = enum<ArrivalStatus> 1
    printfn $"Arrival Status: {status2} ({status2:D})"
    // The example displays the following output:
    //       Arrival Status: Early (1)
    
    Dim status2 As ArrivalStatus2 = CType(1, ArrivalStatus2)
    Console.WriteLine("Arrival Status: {0} ({0:D})", status2)
    ' The example displays the following output:
    '       Arrival Status: Early (1)
    
  • Chiamando il relativo costruttore implicito senza parametri. Come illustrato nell'esempio seguente, in questo caso il valore sottostante dell'istanza di enumerazione è 0. Tuttavia, questo non è necessariamente il valore di una costante valida nell'enumerazione .

    ArrivalStatus status1 = new ArrivalStatus();
    Console.WriteLine("Arrival Status: {0} ({0:D})", status1);
    // The example displays the following output:
    //       Arrival Status: OnTime (0)
    
    let status1 = ArrivalStatus()
    printfn $"Arrival Status: {status1} ({status1:D})"
    // The example displays the following output:
    //       Arrival Status: OnTime (0)
    
    Dim status1 As New ArrivalStatus2()
    Console.WriteLine("Arrival Status: {0} ({0:D})", status1)
    ' The example displays the following output:
    '        Arrival Status: OnTime (0)
    
  • Chiamando il Parse metodo o TryParse per analizzare una stringa contenente il nome di una costante nell'enumerazione . Per altre informazioni, vedere la sezione Analizzare i valori di enumerazione.

  • Chiamando il ToObject metodo per convertire un valore integrale in un tipo di enumerazione. Per altre informazioni, vedere la sezione Eseguire conversioni .

Procedure consigliate per l'enumerazione

È consigliabile usare le procedure consigliate seguenti quando si definiscono i tipi di enumerazione:

  • Se non è stato definito un membro di enumerazione il cui valore è 0, è consigliabile creare una None costante enumerata. Per impostazione predefinita, la memoria usata per l'enumerazione viene inizializzata su zero da Common Language Runtime. Di conseguenza, se non si definisce una costante il cui valore è zero, l'enumerazione conterrà un valore non valido al momento della creazione.

  • Se esiste un caso predefinito ovvio che l'applicazione deve rappresentare, è consigliabile usare una costante enumerata il cui valore è zero per rappresentarlo. Se non esiste un caso predefinito, è consigliabile utilizzare una costante enumerata il cui valore è zero per specificare il caso che non è rappresentato da nessuna delle altre costanti enumerate.

  • Non specificare costanti enumerate riservate per uso futuro.

  • Quando si definisce un metodo o una proprietà che accetta una costante enumerata come valore, è consigliabile convalidare il valore. Il motivo è che è possibile eseguire il cast di un valore numerico al tipo di enumerazione anche se tale valore numerico non è definito nell'enumerazione .

Altre procedure consigliate per i tipi di enumerazione le cui costanti sono campi di bit sono elencate nella sezione Membri non esclusivi e attributo Flags.

Eseguire operazioni con enumerazioni

Non è possibile definire nuovi metodi quando si crea un'enumerazione. Tuttavia, un tipo di enumerazione eredita un set completo di metodi statici e di istanza dalla Enum classe . Le sezioni seguenti esaminano la maggior parte di questi metodi, oltre a diversi altri metodi comunemente usati quando si usano valori di enumerazione.

Eseguire conversioni

È possibile eseguire la conversione tra un membro di enumerazione e il relativo tipo sottostante usando un cast (in C# e F#) o un operatore di conversione (in Visual Basic). In F# viene usata anche la enum funzione . Nell'esempio seguente vengono utilizzati operatori di cast o conversione per eseguire conversioni da un numero intero a un valore di enumerazione e da un valore di enumerazione a un numero intero.

int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus)value3;

int value4 = (int)status3;
let value3 = 2
let status3 = enum<ArrivalStatus> value3

let value4 = int status3
Dim value3 As Integer = 2
Dim status3 As ArrivalStatus2 = CType(value3, ArrivalStatus2)

Dim value4 As Integer = CInt(status3)

La Enum classe include anche un ToObject metodo che converte un valore di qualsiasi tipo integrale in un valore di enumerazione. Nell'esempio seguente viene utilizzato il ToObject(Type, Int32) metodo per convertire un oggetto Int32 in un ArrivalStatus valore . Si noti che, poiché restituisce ToObject un valore di tipo Object, l'uso di un operatore di cast o conversione può comunque essere necessario per eseguire il cast dell'oggetto al tipo di enumerazione.

int number = -1;
ArrivalStatus arrived = (ArrivalStatus)ArrivalStatus.ToObject(typeof(ArrivalStatus), number);
let number = -1
let arrived = ArrivalStatus.ToObject(typeof<ArrivalStatus>, number) :?> ArrivalStatus
Dim number As Integer = -1
Dim arrived As ArrivalStatus2 = CType(ArrivalStatus2.ToObject(GetType(ArrivalStatus2), number), ArrivalStatus2)

Quando si converte un numero intero in un valore di enumerazione, è possibile assegnare un valore che non è effettivamente un membro dell'enumerazione. Per evitare questo problema, è possibile passare l'intero al IsDefined metodo prima di eseguire la conversione. Nell'esempio seguente viene utilizzato questo metodo per determinare se gli elementi in una matrice di valori integer possono essere convertiti in ArrivalStatus valori .

using System;

public class Example3
{
    public static void Main()
    {
        int[] values = { -3, -1, 0, 1, 5, Int32.MaxValue };
        foreach (var value in values)
        {
            ArrivalStatus status;
            if (Enum.IsDefined(typeof(ArrivalStatus), value))
                status = (ArrivalStatus)value;
            else
                status = ArrivalStatus.Unknown;
            Console.WriteLine("Converted {0:N0} to {1}", value, status);
        }
    }
}
// The example displays the following output:
//       Converted -3 to Unknown
//       Converted -1 to Late
//       Converted 0 to OnTime
//       Converted 1 to Early
//       Converted 5 to Unknown
//       Converted 2,147,483,647 to Unknown
open System

type ArrivalStatus =
    | Unknown = -3
    | Late = -1
    | OnTime = 0
    | Early = 1

let values = [ -3; -1; 0; 1; 5; Int32.MaxValue ]
for value in values do
    let status =
        if Enum.IsDefined(typeof<ArrivalStatus>, value) then
            enum value
        else
            ArrivalStatus.Unknown
    printfn $"Converted {value:N0} to {status}"
// The example displays the following output:
//       Converted -3 to Unknown
//       Converted -1 to Late
//       Converted 0 to OnTime
//       Converted 1 to Early
//       Converted 5 to Unknown
//       Converted 2,147,483,647 to Unknown
Public Enum ArrivalStatus4 As Integer
    Unknown = -3
    Late = -1
    OnTime = 0
    Early = 1
End Enum

Module Example4
    Public Sub Main()
        Dim values() As Integer = {-3, -1, 0, 1, 5, Int32.MaxValue}
        For Each value In values
            Dim status As ArrivalStatus4
            If [Enum].IsDefined(GetType(ArrivalStatus4), value) Then
                status = CType(value, ArrivalStatus4)
            Else
                status = ArrivalStatus4.Unknown
            End If
            Console.WriteLine("Converted {0:N0} to {1}", value, status)
        Next
    End Sub
End Module
' The example displays the following output:
'       Converted -3 to Unknown
'       Converted -1 to Late
'       Converted 0 to OnTime
'       Converted 1 to Early
'       Converted 5 to Unknown
'       Converted 2,147,483,647 to Unknown

Sebbene la Enum classe fornisca implementazioni di interfaccia esplicite dell'interfaccia IConvertible per la conversione da un valore di enumerazione a un tipo integrale, è necessario usare i metodi della Convert classe, ad esempio ToInt32, per eseguire queste conversioni. Nell'esempio seguente viene illustrato come utilizzare il GetUnderlyingType metodo insieme al Convert.ChangeType metodo per convertire un valore di enumerazione nel tipo sottostante. Si noti che questo esempio non richiede che il tipo sottostante dell'enumerazione sia noto in fase di compilazione.

ArrivalStatus status = ArrivalStatus.Early;
var number = Convert.ChangeType(status, Enum.GetUnderlyingType(typeof(ArrivalStatus)));
Console.WriteLine("Converted {0} to {1}", status, number);
// The example displays the following output:
//       Converted Early to 1
let status = ArrivalStatus.Early
let number = Convert.ChangeType(status, Enum.GetUnderlyingType typeof<ArrivalStatus>)
printfn $"Converted {status} to {number}"
// The example displays the following output:
//       Converted Early to 1
Dim status As ArrivalStatus5 = ArrivalStatus5.Early
Dim number = Convert.ChangeType(status, [Enum].GetUnderlyingType(GetType(ArrivalStatus5)))
Console.WriteLine("Converted {0} to {1}", status, number)
' The example displays the following output:
'       Converted Early to 1

Analizzare i valori di enumerazione

I Parse metodi e TryParse consentono di convertire la rappresentazione di stringa di un valore di enumerazione in tale valore. La rappresentazione di stringa può essere il nome o il valore sottostante di una costante di enumerazione. Si noti che i metodi di analisi convertiranno correttamente rappresentazioni di stringa di numeri che non sono membri di una particolare enumerazione se le stringhe possono essere convertite in un valore del tipo sottostante dell'enumerazione. Per evitare questo problema, è possibile chiamare il IsDefined metodo per assicurarsi che il risultato del metodo di analisi sia un valore di enumerazione valido. L'esempio illustra questo approccio e illustra le chiamate ai Parse(Type, String) metodi e Enum.TryParse<TEnum>(String, TEnum) . Si noti che il metodo di analisi non generico restituisce un oggetto che potrebbe essere necessario eseguire il cast (in C# e F#) o convertire (in Visual Basic) nel tipo di enumerazione appropriato.

string number = "-1";
string name = "Early";

try
{
    ArrivalStatus status1 = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), number);
    if (!(Enum.IsDefined(typeof(ArrivalStatus), status1)))
        status1 = ArrivalStatus.Unknown;
    Console.WriteLine("Converted '{0}' to {1}", number, status1);
}
catch (FormatException)
{
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
                      number);
}

ArrivalStatus status2;
if (Enum.TryParse<ArrivalStatus>(name, out status2))
{
    if (!(Enum.IsDefined(typeof(ArrivalStatus), status2)))
        status2 = ArrivalStatus.Unknown;
    Console.WriteLine("Converted '{0}' to {1}", name, status2);
}
else
{
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
                      number);
}
// The example displays the following output:
//       Converted '-1' to Late
//       Converted 'Early' to Early
let number = "-1"
let name = "Early"

try
    let status1 = Enum.Parse(typeof<ArrivalStatus>, number) :?> ArrivalStatus
    let status1 =
        if not (Enum.IsDefined(typeof<ArrivalStatus>, status1) ) then
            ArrivalStatus.Unknown
        else 
            status1
        
    printfn $"Converted '{number}' to {status1}"
with :? FormatException ->
    printfn $"Unable to convert '{number}' to an ArrivalStatus value."

match Enum.TryParse<ArrivalStatus> name with
| true, status2 ->
    let status2 = 
        if not (Enum.IsDefined(typeof<ArrivalStatus>, status2) ) then
            ArrivalStatus.Unknown
        else 
            status2
    printfn $"Converted '{name}' to {status2}"
| _ ->
    printfn $"Unable to convert '{number}' to an ArrivalStatus value."
// The example displays the following output:
//       Converted '-1' to Late
//       Converted 'Early' to Early
Dim number As String = "-1"
Dim name As String = "Early"
Dim invalid As String = "32"

Try
    Dim status1 As ArrivalStatus8 = CType([Enum].Parse(GetType(ArrivalStatus8), number), ArrivalStatus8)
    If Not [Enum].IsDefined(GetType(ArrivalStatus8), status1) Then status1 = ArrivalStatus8.Unknown
    Console.WriteLine("Converted '{0}' to {1}", number, status1)
Catch e As FormatException
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus8 value.",
                   number)
End Try

Dim status2 As ArrivalStatus8
If [Enum].TryParse(Of ArrivalStatus8)(name, status2) Then
    If Not [Enum].IsDefined(GetType(ArrivalStatus8), status2) Then status2 = ArrivalStatus8.Unknown
    Console.WriteLine("Converted '{0}' to {1}", name, status2)
Else
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus8 value.",
                   number)
End If
' The example displays the following output:
'       Converted '-1' to Late
'       Converted 'Early' to Early

Formattare i valori di enumerazione

È possibile convertire i valori di enumerazione nelle relative rappresentazioni di stringa chiamando il metodo statico Format , nonché gli overload del metodo di istanza ToString . È possibile usare una stringa di formato per controllare il modo preciso in cui un valore di enumerazione viene rappresentato come stringa. Per altre informazioni, vedere Stringhe di formato di enumerazione. Nell'esempio seguente vengono utilizzate ognuna delle stringhe di formato di enumerazione supportate ("G" o "g", "D" o "d", "X" o "x" e "F" o "f") per convertire un membro dell'enumerazione ArrivalStatus nelle relative rappresentazioni di stringa.

string[] formats = { "G", "F", "D", "X" };
ArrivalStatus status = ArrivalStatus.Late;
foreach (var fmt in formats)
    Console.WriteLine(status.ToString(fmt));

// The example displays the following output:
//       Late
//       Late
//       -1
//       FFFFFFFF
let formats = [ "G"; "F"; "D"; "X" ]
let status = ArrivalStatus.Late
for fmt in formats do
    printfn $"{status.ToString fmt}"

// The example displays the following output:
//       Late
//       Late
//       -1
//       FFFFFFFF
Dim formats() As String = {"G", "F", "D", "X"}
Dim status As ArrivalStatus6 = ArrivalStatus6.Late
For Each fmt As String In formats
    Console.WriteLine(status.ToString(fmt))
Next
' The example displays the following output:
'       Late
'       Late
'       -1
'       FFFFFFFF

Eseguire l'iterazione dei membri dell'enumerazione

Il Enum tipo non implementa l'interfaccia IEnumerable o IEnumerable<T> , che consente di scorrere i membri di una raccolta usando un foreach costrutto (in C#), for..in (in F#) o For Each (in Visual Basic). Tuttavia, è possibile enumerare i membri in uno dei due modi seguenti.

  • È possibile chiamare il GetNames metodo per recuperare una matrice di stringhe contenente i nomi dei membri dell'enumerazione. Successivamente, per ogni elemento della matrice di stringhe, è possibile chiamare il Parse metodo per convertire la stringa nel relativo valore di enumerazione equivalente. Questo approccio viene illustrato nell'esempio seguente:

    string[] names = Enum.GetNames(typeof(ArrivalStatus));
    Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name);
    Array.Sort(names);
    foreach (var name in names)
    {
        ArrivalStatus status = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), name);
        Console.WriteLine("   {0} ({0:D})", status);
    }
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          Early (1)
    //          Late (-1)
    //          OnTime (0)
    //          Unknown (-3)
    
    let names = Enum.GetNames typeof<ArrivalStatus>
    printfn $"Members of {nameof ArrivalStatus}:"
    let names = Array.sort names
    for name in names do
        let status = Enum.Parse(typeof<ArrivalStatus>, name) :?> ArrivalStatus
        printfn $"   {status} ({status:D})"
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          Early (1)
    //          Late (-1)
    //          OnTime (0)
    //          Unknown (-3)
    
    Dim names() As String = [Enum].GetNames(GetType(ArrivalStatus7))
    Console.WriteLine("Members of {0}:", GetType(ArrivalStatus7).Name)
    Array.Sort(names)
    For Each name In names
        Dim status As ArrivalStatus7 = CType([Enum].Parse(GetType(ArrivalStatus7), name),
                                   ArrivalStatus7)
        Console.WriteLine("   {0} ({0:D})", status)
    Next
    ' The example displays the following output:
    '       Members of ArrivalStatus7:
    '          Early (1)
    '          Late (-1)
    '          OnTime (0)
    '          Unknown (-3)
    
  • È possibile chiamare il GetValues metodo per recuperare una matrice contenente i valori sottostanti nell'enumerazione . Successivamente, per ogni elemento della matrice, è possibile chiamare il ToObject metodo per convertire l'intero nel valore di enumerazione equivalente. Questo approccio viene illustrato nell'esempio seguente:

    var values = Enum.GetValues(typeof(ArrivalStatus));
    Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name);
    foreach (ArrivalStatus status in values)
    {
        Console.WriteLine("   {0} ({0:D})", status);
    }
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          OnTime (0)
    //          Early (1)
    //          Unknown (-3)
    //          Late (-1)
    
    let values = Enum.GetValues typeof<ArrivalStatus>
    printfn $"Members of {nameof ArrivalStatus}:"
    for status in values do
        printfn $"   {status} ({status:D})"
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          OnTime (0)
    //          Early (1)
    //          Unknown (-3)
    //          Late (-1)
    
    Dim values = [Enum].GetValues(GetType(ArrivalStatus7))
    Console.WriteLine("Members of {0}:", GetType(ArrivalStatus7).Name)
    For Each value In values
        Dim status As ArrivalStatus7 = CType([Enum].ToObject(GetType(ArrivalStatus7), value),
                                         ArrivalStatus7)
        Console.WriteLine("   {0} ({0:D})", status)
    Next
    ' The example displays the following output:
    '       Members of ArrivalStatus7:
    '          OnTime (0)
    '          Early (1)
    '          Unknown (-3)
    '          Late (-1)
    

Membri non esclusivi e attributo Flags

Un uso comune di un'enumerazione consiste nel rappresentare un set di valori che si escludono a vicenda. Ad esempio, un'istanza ArrivalStatus può avere un valore , OnTimeEarlyo Late. Non ha senso che il valore di un'istanza ArrivalStatus rifletta più di una costante di enumerazione.

In altri casi, tuttavia, il valore di un oggetto di enumerazione può includere più membri di enumerazione e ogni membro rappresenta un campo di bit nel valore di enumerazione. L'attributo FlagsAttribute può essere usato per indicare che l'enumerazione è costituita da campi di bit. Ad esempio, un'enumerazione denominata Pets può essere usata per indicare i tipi di animali domestici in una famiglia. Può essere definito come segue.

[Flags]
public enum Pets
{
    None = 0, Dog = 1, Cat = 2, Bird = 4, Rodent = 8,
    Reptile = 16, Other = 32
};
[<Flags>] 
type Pets =
    | None = 0
    | Dog = 1
    | Cat = 2
    | Bird = 4
    | Rodent = 8
    | Reptile = 16
    | Other = 32
<Flags> Public Enum Pets As Integer
   None = 0
   Dog = 1
   Cat = 2
   Bird = 4
   Rodent = 8
   Reptile = 16
   Other = 32
End Enum

L'enumerazione Pets può quindi essere usata come illustrato nell'esempio seguente.

Pets familyPets = Pets.Dog | Pets.Cat;
Console.WriteLine("Pets: {0:G} ({0:D})", familyPets);
// The example displays the following output:
//       Pets: Dog, Cat (3)
let familyPets = Pets.Dog ||| Pets.Cat
printfn $"Pets: {familyPets:G} ({familyPets:D})"
// The example displays the following output:
//       Pets: Dog, Cat (3)
Dim familyPets As Pets = Pets.Dog Or Pets.Cat
Console.WriteLine("Pets: {0:G} ({0:D})", familyPets)
' The example displays the following output:
'       Pets: Dog, Cat (3)

Per definire un'enumerazione bit per bit e applicare l'attributo, è consigliabile usare le FlagsAttribute procedure consigliate seguenti.

  • Usare l'attributo personalizzato per un'enumerazione FlagsAttribute solo se un'operazione bit per bit (AND, OR, EXCLUSIVE OR) deve essere eseguita su un valore numerico.

  • Definire le costanti di enumerazione nelle potenze di due, ovvero 1, 2, 4, 8 e così via. Ciò significa che i singoli flag nelle costanti di enumerazione combinata non si sovrappongono.

  • Prendere in considerazione la creazione di una costante enumerata per le combinazioni di flag di uso comune. Ad esempio, se si dispone di un'enumerazione usata per le operazioni di I/O di file che contiene le costanti Read = 1 enumerate e Write = 2, è consigliabile creare la costante ReadWrite = Read OR Writeenumerata , che combina i Read flag e Write . Inoltre, l'operazione OR bit per bit usata per combinare i flag potrebbe essere considerata un concetto avanzato in alcune circostanze che non devono essere necessarie per attività semplici.

  • Prestare attenzione se si definisce un numero negativo come costante enumerata di flag perché molte posizioni dei flag potrebbero essere impostate su 1, che potrebbero generare confusione nel codice e incoraggiare gli errori di codifica.

  • Un modo pratico per verificare se un flag è impostato in un valore numerico consiste nel chiamare il metodo di istanza HasFlag , come illustrato nell'esempio seguente.

    Pets familyPets = Pets.Dog | Pets.Cat;
    if (familyPets.HasFlag(Pets.Dog))
        Console.WriteLine("The family has a dog.");
    // The example displays the following output:
    //       The family has a dog.
    
    let familyPets = Pets.Dog ||| Pets.Cat
    if familyPets.HasFlag Pets.Dog then
        printfn "The family has a dog."
    // The example displays the following output:
    //       The family has a dog.
    
    Dim familyPets As Pets = Pets.Dog Or Pets.Cat
    If familyPets.HasFlag(Pets.Dog) Then
        Console.WriteLine("The family has a dog.")
    End If
    ' The example displays the following output:
    '       The family has a dog.
    

    Equivale a eseguire un'operazione AND bit per bit tra il valore numerico e la costante enumerata del flag, che imposta tutti i bit nel valore numerico su zero che non corrispondono al flag e quindi verifica se il risultato di tale operazione è uguale alla costante enumerata del flag. Questo è illustrato nell'esempio seguente.

    Pets familyPets = Pets.Dog | Pets.Cat;
    if ((familyPets & Pets.Dog) == Pets.Dog)
        Console.WriteLine("The family has a dog.");
    // The example displays the following output:
    //       The family has a dog.
    
    let familyPets = Pets.Dog ||| Pets.Cat
    if (familyPets &&& Pets.Dog) = Pets.Dog then
        printfn "The family has a dog."
    // The example displays the following output:
    //       The family has a dog.
    
    Dim familyPets As Pets = Pets.Dog Or Pets.Cat
    If familyPets And Pets.Dog = Pets.Dog Then
        Console.WriteLine("The family has a dog.")
    End If
    ' The example displays the following output:
    '       The family has a dog.
    
  • Usare None come nome della costante enumerata flag il cui valore è zero. Non è possibile utilizzare la None costante enumerata in un'operazione AND bit per bit per testare un flag perché il risultato è sempre zero. Tuttavia, è possibile eseguire un confronto logico, non bit per bit, tra il valore numerico e la None costante enumerata per determinare se vengono impostati bit nel valore numerico. Questo è illustrato nell'esempio seguente.

    Pets familyPets = Pets.Dog | Pets.Cat;
    if (familyPets == Pets.None)
        Console.WriteLine("The family has no pets.");
    else
        Console.WriteLine("The family has pets.");
    // The example displays the following output:
    //       The family has pets.
    
    let familyPets = Pets.Dog ||| Pets.Cat
    if familyPets = Pets.None then
        printfn "The family has no pets."
    else
        printfn "The family has pets."
    // The example displays the following output:
    //       The family has pets.
    
    Dim familyPets As Pets = Pets.Dog Or Pets.Cat
    If familyPets = Pets.None Then
        Console.WriteLine("The family has no pets.")
    Else
        Console.WriteLine("The family has pets.")
    End If
    ' The example displays the following output:
    '       The family has pets.
    
  • Non definire un valore di enumerazione esclusivamente per eseguire il mirroring dello stato dell'enumerazione stessa. Ad esempio, non definire una costante enumerata che contrassegna semplicemente la fine dell'enumerazione. Se è necessario determinare l'ultimo valore dell'enumerazione, verificare la presenza di tale valore in modo esplicito. Inoltre, è possibile eseguire un controllo di intervallo per la prima e l'ultima costante enumerata se tutti i valori all'interno dell'intervallo sono validi.

Aggiungere metodi di enumerazione

Poiché i tipi di enumerazione sono definiti dalle strutture del linguaggio, ad esempio enum (C#) e Enum (Visual Basic), non è possibile definire metodi personalizzati per un tipo di enumerazione diverso da quelli ereditati dalla Enum classe . Tuttavia, è possibile usare metodi di estensione per aggiungere funzionalità a un particolare tipo di enumerazione.

Nell'esempio seguente, l'enumerazione Grades rappresenta il voto che uno studente potrebbe ricevere in un corso. Il metodo di estensione denominato Passing viene aggiunto al tipo Grades in modo che ogni istanza di tale tipo ora "sa" se rappresenta un voto sufficiente oppure no. La Extensions classe contiene anche una variabile di lettura/scrittura statica che definisce il grado minimo di passaggio. Il valore restituito del Passing metodo di estensione riflette il valore corrente di tale variabile.

using System;

// Define an enumeration to represent student grades.
public enum Grades { F = 0, D = 1, C = 2, B = 3, A = 4 };

// Define an extension method for the Grades enumeration.
public static class Extensions
{
    public static Grades minPassing = Grades.D;

    public static bool Passing(this Grades grade)
    {
        return grade >= minPassing;
    }
}

class Example8
{
    static void Main()
    {
        Grades g1 = Grades.D;
        Grades g2 = Grades.F;
        Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
        Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");

        Extensions.minPassing = Grades.C;
        Console.WriteLine("\nRaising the bar!\n");
        Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
        Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");
    }
}
// The exmaple displays the following output:
//       D is a passing grade.
//       F is not a passing grade.
//
//       Raising the bar!
//
//       D is not a passing grade.
//       F is not a passing grade.
open System
open System.Runtime.CompilerServices
// Define an enumeration to represent student grades.
type Grades =
    | F = 0
    | D = 1
    | C = 2
    | B = 3
    | A = 4

let mutable minPassing = Grades.D

// Define an extension method for the Grades enumeration.
[<Extension>]
type Extensions =
    [<Extension>]
    static member Passing(grade) = grade >= minPassing

let g1 = Grades.D
let g2 = Grades.F
printfn $"""{g1} {if g1.Passing() then "is" else "is not"} a passing grade."""
printfn $"""{g2} {if g2.Passing() then "is" else "is not"} a passing grade."""

minPassing <- Grades.C
printfn "\nRaising the bar!\n"
printfn $"""{g1} {if g1.Passing() then "is" else "is not"} a passing grade."""
printfn $"""{g2} {if g2.Passing() then "is" else "is not"} a passing grade."""
// The exmaple displays the following output:
//       D is a passing grade.
//       F is not a passing grade.
//
//       Raising the bar!
//
//       D is not a passing grade.
//       F is not a passing grade.
Imports System.Runtime.CompilerServices

' Define an enumeration to represent student grades.
Public Enum Grades As Integer
   F = 0
   D = 1
   C = 2
   B = 3
   A = 4
End Enum   

' Define an extension method for the Grades enumeration.
Public Module Extensions
  Public minPassing As Grades = Grades.D
 
  <Extension>
  Public Function Passing(grade As Grades) As Boolean
     Return grade >= minPassing
  End Function
End Module

Public Module Example
  Public Sub Main()
      Dim g1 As Grades = Grades.D
      Dim g2 As Grades = Grades.F
      Console.WriteLine("{0} {1} a passing grade.", 
                        g1, If(g1.Passing(), "is", "is not"))
      Console.WriteLine("{0} {1} a passing grade.", 
                        g2, If(g2.Passing(), "is", "is not"))
      Console.WriteLine()
      
      Extensions.minPassing = Grades.C
      Console.WriteLine("Raising the bar!")
      Console.WriteLine()
      Console.WriteLine("{0} {1} a passing grade.", 
                        g1, If(g1.Passing(), "is", "is not"))
      Console.WriteLine("{0} {1} a passing grade.", 
                        g2, If(g2.Passing(), "is", "is not"))
  End Sub
End Module
' The exmaple displays the following output:
'       D is a passing grade.
'       F is not a passing grade.
'       
'       Raising the bar!
'       
'       D is not a passing grade.
'       F is not a passing grade.

Esempi

Nell'esempio seguente viene illustrato l'uso di un'enumerazione per rappresentare i valori denominati e un'altra enumerazione per rappresentare i campi di bit denominati.

using System;

public class EnumTest {
    enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
    enum BoilingPoints { Celsius = 100, Fahrenheit = 212 };
    [Flags]
    enum Colors { Red = 1, Green = 2, Blue = 4, Yellow = 8 };

    public static void Main() {

        Type weekdays = typeof(Days);
        Type boiling = typeof(BoilingPoints);

        Console.WriteLine("The days of the week, and their corresponding values in the Days Enum are:");

        foreach ( string s in Enum.GetNames(weekdays) )
            Console.WriteLine( "{0,-11}= {1}", s, Enum.Format( weekdays, Enum.Parse(weekdays, s), "d"));

        Console.WriteLine();
        Console.WriteLine("Enums can also be created which have values that represent some meaningful amount.");
        Console.WriteLine("The BoilingPoints Enum defines the following items, and corresponding values:");

        foreach ( string s in Enum.GetNames(boiling) )
            Console.WriteLine( "{0,-11}= {1}", s, Enum.Format(boiling, Enum.Parse(boiling, s), "d"));

        Colors myColors = Colors.Red | Colors.Blue | Colors.Yellow;
        Console.WriteLine();
        Console.WriteLine("myColors holds a combination of colors. Namely: {0}", myColors);
    }
}
open System

type Days =
    | Saturday = 0
    | Sunday = 1
    | Monday = 2
    | Tuesday = 3
    | Wednesday = 4
    | Thursday = 5
    | Friday = 6

type BoilingPoints =
    | Celsius = 100
    | Fahrenheit = 212

[<Flags>]
type Colors =
    | Red = 1
    | Green = 2
    | Blue = 4
    | Yellow = 8

let weekdays = typeof<Days>
let boiling = typeof<BoilingPoints>

printfn "The days of the week, and their corresponding values in the Days Enum are:"

for s in Enum.GetNames weekdays do
    printfn $"""{s,-11}= {Enum.Format(weekdays, Enum.Parse(weekdays, s), "d")}"""

printfn "\nEnums can also be created which have values that represent some meaningful amount."
printfn "The BoilingPoints Enum defines the following items, and corresponding values:"

for s in Enum.GetNames boiling do
    printfn $"""{s,-11}= {Enum.Format(boiling, Enum.Parse(boiling, s), "d")}"""

let myColors = Colors.Red ||| Colors.Blue ||| Colors.Yellow
printfn $"\nmyColors holds a combination of colors. Namely: {myColors}"
Public Class EnumTest
    Enum Days
        Saturday
        Sunday
        Monday
        Tuesday
        Wednesday
        Thursday
        Friday
    End Enum 
    
    Enum BoilingPoints
        Celsius = 100
        Fahrenheit = 212
    End Enum 
    
    <Flags()> _
    Enum Colors
        Red = 1
        Green = 2
        Blue = 4
        Yellow = 8
    End Enum 

    Public Shared Sub Main()
        Dim weekdays As Type = GetType(Days)
        Dim boiling As Type = GetType(BoilingPoints)

        Console.WriteLine("The days of the week, and their corresponding values in the Days Enum are:")

        Dim s As String
        For Each s In  [Enum].GetNames(weekdays)
            Console.WriteLine("{0,-11} = {1}", s, [Enum].Format(weekdays, [Enum].Parse(weekdays, s), "d"))
        
        Next s
        Console.WriteLine()
        Console.WriteLine("Enums can also be created which have values that represent some meaningful amount.")
        Console.WriteLine("The BoilingPoints Enum defines the following items, and corresponding values:")

        For Each s In  [Enum].GetNames(boiling)
            Console.WriteLine("{0,-11} = {1}", s, [Enum].Format(boiling, [Enum].Parse(boiling, s), "d"))
        Next s

        Dim myColors As Colors = Colors.Red Or Colors.Blue Or Colors.Yellow
        Console.WriteLine()
        Console.WriteLine("myColors holds a combination of colors. Namely: {0}", myColors)
    End Sub 
End Class