Ricerca…
introduzione
Un enum può derivare da uno dei seguenti tipi: byte, sbyte, short, ushort, int, uint, long, ulong. Il valore predefinito è int e può essere modificato specificando il tipo nella definizione enum:
public enum Weekday: byte {lunedì = 1, martedì = 2, mercoledì = 3, giovedì = 4, venerdì = 5}
Questo è utile quando P / Invoca codice nativo, mappatura a origini dati e circostanze simili. In generale, si dovrebbe usare l'int predefinito, perché la maggior parte degli sviluppatori si aspetta che un enum sia int.
Sintassi
- enum Colors {Red, Green, Blue} // Dichiarazione Enum
- enum Colori: byte {rosso, verde, blu} // Dichiarazione con tipo specifico
- enum Colors {Red = 23, Green = 45, Blue = 12} // Dichiarazione con valori definiti
- Colors.Red // Accede a un elemento di un Enum
- int value = (int) Colors.Red // Ottieni il valore int di un elemento enum
- Colors color = (Colors) intValue // Ottieni un elemento enum da int
Osservazioni
Un enum (abbreviazione di "tipo enumerato") è un tipo costituito da un insieme di costanti nominate, rappresentate da un identificatore specifico del tipo.
Le enumerazioni sono più utili per rappresentare concetti che hanno un numero (solitamente piccolo) di valori discreti possibili. Ad esempio, possono essere utilizzati per rappresentare un giorno della settimana o un mese dell'anno. Possono anche essere usati come flag che possono essere combinati o controllati, usando operazioni bit a bit.
Ottieni tutti i valori dei membri di un enum
enum MyEnum
{
One,
Two,
Three
}
foreach(MyEnum e in Enum.GetValues(typeof(MyEnum)))
Console.WriteLine(e);
Questo stamperà:
One
Two
Three
Enum come bandiere
Il FlagsAttribute
può essere applicato a un enum che modifica il comportamento di ToString()
in modo che corrisponda alla natura dell'enum:
[Flags]
enum MyEnum
{
//None = 0, can be used but not combined in bitwise operations
FlagA = 1,
FlagB = 2,
FlagC = 4,
FlagD = 8
//you must use powers of two or combinations of powers of two
//for bitwise operations to work
}
var twoFlags = MyEnum.FlagA | MyEnum.FlagB;
// This will enumerate all the flags in the variable: "FlagA, FlagB".
Console.WriteLine(twoFlags);
Poiché FlagsAttribute
si basa sulle costanti di enumerazione per essere poteri di due (o le loro combinazioni) ei valori enum sono in definitiva valori numerici, si è limitati dalla dimensione del tipo numerico sottostante. Il più grande tipo numerico disponibile che è possibile utilizzare è UInt64
, che consente di specificare 64 costanti enum flag distinte (non combinate). La parola chiave enum
imposta automaticamente il tipo sottostante int
, che è Int32
. Il compilatore consentirà la dichiarazione di valori più ampi di 32 bit. Quelli si avvolgeranno senza avviso e generano due o più membri enum dello stesso valore. Pertanto, se un enum è pensato per contenere un set di bit di oltre 32 flag, è necessario specificare esplicitamente un tipo più grande:
public enum BigEnum : ulong
{
BigValue = 1 << 63
}
Sebbene i flag siano spesso solo un singolo bit, possono essere combinati in "set" denominati per un utilizzo più semplice.
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
Per evitare di compitare i valori decimali delle potenze di due, l' operatore di spostamento a sinistra (<<) può anche essere usato per dichiarare lo stesso enum
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
A partire da C # 7.0, possono essere usati anche i letterali binari .
Per verificare se il valore della variabile enum ha un determinato flag impostato, è possibile utilizzare il metodo HasFlag
. Diciamo che abbiamo
[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Three = 4
}
E un value
var value = MyEnum.One | MyEnum.Two;
Con HasFlag
possiamo controllare se uno qualsiasi dei flag è impostato
if(value.HasFlag(MyEnum.One))
Console.WriteLine("Enum has One");
if(value.HasFlag(MyEnum.Two))
Console.WriteLine("Enum has Two");
if(value.HasFlag(MyEnum.Three))
Console.WriteLine("Enum has Three");
Inoltre possiamo scorrere tutti i valori di enum per ottenere tutti i flag impostati
var type = typeof(MyEnum);
var names = Enum.GetNames(type);
foreach (var name in names)
{
var item = (MyEnum)Enum.Parse(type, name);
if (value.HasFlag(item))
Console.WriteLine("Enum has " + name);
}
O
foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))
{
if(value.HasFlag(flagToCheck))
{
Console.WriteLine("Enum has " + flagToCheck);
}
}
Tutti e tre gli esempi stamperanno:
Enum has One
Enum has Two
Prova i valori enum in stile flags con logica bit a bit
Un valore enum in stile flags deve essere testato con logica bit a bit perché potrebbe non corrispondere a nessun singolo valore.
[Flags]
enum FlagsEnum
{
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option2And3 = Option2 | Option3;
Default = Option1 | Option3,
}
Il valore Default
è in realtà una combinazione di altri due uniti con un OR bit a bit. Quindi per testare la presenza di un flag dobbiamo usare un AND bit a bit.
var value = FlagsEnum.Default;
bool isOption2And3Set = (value & FlagsEnum.Option2And3) == FlagsEnum.Option2And3;
Assert.True(isOption2And3Set);
Enum per corda e schiena
public enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
// Enum to string
string thursday = DayOfWeek.Thursday.ToString(); // "Thursday"
string seventhDay = Enum.GetName(typeof(DayOfWeek), 6); // "Saturday"
string monday = Enum.GetName(typeof(DayOfWeek), DayOfWeek.Monday); // "Monday"
// String to enum (.NET 4.0+ only - see below for alternative syntax for earlier .NET versions)
DayOfWeek tuesday;
Enum.TryParse("Tuesday", out tuesday); // DayOfWeek.Tuesday
DayOfWeek sunday;
bool matchFound1 = Enum.TryParse("SUNDAY", out sunday); // Returns false (case-sensitive match)
DayOfWeek wednesday;
bool matchFound2 = Enum.TryParse("WEDNESDAY", true, out wednesday); // Returns true; DayOfWeek.Wednesday (case-insensitive match)
// String to enum (all .NET versions)
DayOfWeek friday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Friday"); // DayOfWeek.Friday
DayOfWeek caturday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Caturady"); // Thows ArgumentException
// All names of an enum type as strings
string[] weekdays = Enum.GetNames(typeof(DayOfWeek));
Valore predefinito per enum == ZERO
Il valore predefinito per un enum è zero . Se un enum non definisce un oggetto con un valore pari a zero, il suo valore predefinito sarà zero.
public class Program
{
enum EnumExample
{
one = 1,
two = 2
}
public void Main()
{
var e = default(EnumExample);
if (e == EnumExample.one)
Console.WriteLine("defaults to one");
else
Console.WriteLine("Unknown");
}
}
Esempio: https://dotnetfiddle.net/l5Rwie
Nozioni di base su Enum
Da MSDN :
Un tipo di enumerazione (chiamato anche enumerazione o enumerazione) fornisce un modo efficace per definire un insieme di costanti integrali con nome che possono essere assegnate a una variabile .
Essenzialmente, un enum è un tipo che consente solo un insieme di opzioni finite e ogni opzione corrisponde a un numero. Per impostazione predefinita, tali numeri aumentano nell'ordine in cui i valori sono dichiarati, a partire da zero. Ad esempio, si potrebbe dichiarare un enum per i giorni della settimana:
public enum Day
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Quell'enum potrebbe essere usato così:
// Define variables with values corresponding to specific days
Day myFavoriteDay = Day.Friday;
Day myLeastFavoriteDay = Day.Monday;
// Get the int that corresponds to myFavoriteDay
// Friday is number 4
int myFavoriteDayIndex = (int)myFavoriteDay;
// Get the day that represents number 5
Day dayFive = (Day)5;
Per impostazione predefinita, il tipo sottostante di ciascun elemento enum
è int
, ma possono essere utilizzati anche byte
, sbyte
, short
, ushort
, uint
, long
e ulong
. Se si utilizza un tipo diverso da int
, è necessario specificare il tipo utilizzando i due punti dopo il nome dell'enumerazione:
public enum Day : byte
{
// same as before
}
I numeri dopo il nome ora sono byte anziché interi. È possibile ottenere il tipo sottostante dell'enumerazione come segue:
Enum.GetUnderlyingType(typeof(Days)));
Produzione:
System.Byte
Demo: .NET violino
Manipolazione bit a bit tramite enumerazione
Il FlagsAttribute deve essere utilizzato ogni volta che l'enumerable rappresenta una raccolta di flag, piuttosto che un singolo valore. Il valore numerico assegnato a ciascun valore enumerato aiuta a manipolare le enumerazioni utilizzando operatori bit a bit.
Esempio 1: con [bandiere]
[Flags]
enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}
var color = Colors.Red | Colors.Blue;
Console.WriteLine(color.ToString());
stampa rosso, blu
Esempio 2: senza [bandiere]
enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}
var color = Colors.Red | Colors.Blue;
Console.WriteLine(color.ToString());
stampa 3
Usando la notazione << per le bandiere
L'operatore di spostamento a sinistra ( <<
) può essere utilizzato nelle dichiarazioni flag enum per garantire che ogni flag abbia esattamente un 1
nella rappresentazione binaria, come dovrebbero essere le bandiere.
Questo aiuta anche a migliorare la leggibilità di enumerazioni di grandi dimensioni con un sacco di bandiere in esse.
[Flags]
public enum MyEnum
{
None = 0,
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2,
Flag4 = 1 << 3,
Flag5 = 1 << 4,
...
Flag31 = 1 << 30
}
Ora è ovvio che MyEnum
contiene solo flag appropriati e non roba disordinata come Flag30 = 1073741822
(o 1111111111111111111111111111111110 in binario) che è inappropriato.
Aggiunta di ulteriori informazioni di descrizione a un valore enum
In alcuni casi è possibile aggiungere una descrizione aggiuntiva a un valore enum, ad esempio quando il valore enum è meno leggibile di quello che si potrebbe desiderare di visualizzare all'utente. In questi casi è possibile utilizzare la classe System.ComponentModel.DescriptionAttribute
.
Per esempio:
public enum PossibleResults
{
[Description("Success")]
OK = 1,
[Description("File not found")]
FileNotFound = 2,
[Description("Access denied")]
AccessDenied = 3
}
Ora, se vuoi restituire la descrizione di un valore enum specifico, puoi fare quanto segue:
public static string GetDescriptionAttribute(PossibleResults result)
{
return ((DescriptionAttribute)Attribute.GetCustomAttribute((result.GetType().GetField(result.ToString())), typeof(DescriptionAttribute))).Description;
}
static void Main(string[] args)
{
PossibleResults result = PossibleResults.FileNotFound;
Console.WriteLine(result); // Prints "FileNotFound"
Console.WriteLine(GetDescriptionAttribute(result)); // Prints "File not found"
}
Questo può anche essere facilmente trasformato in un metodo di estensione per tutte le enumerazioni:
static class EnumExtensions
{
public static string GetDescription(this Enum enumValue)
{
return ((DescriptionAttribute)Attribute.GetCustomAttribute((enumValue.GetType().GetField(enumValue.ToString())), typeof(DescriptionAttribute))).Description;
}
}
E quindi facilmente utilizzabile in questo modo: Console.WriteLine(result.GetDescription());
Aggiungi e rimuovi i valori dall'enumerazione contrassegnata
Questo codice è per aggiungere e rimuovere un valore da un'istanza enum contrassegnata:
[Flags]
public enum MyEnum
{
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2
}
var value = MyEnum.Flag1;
// set additional value
value |= MyEnum.Flag2; //value is now Flag1, Flag2
value |= MyEnum.Flag3; //value is now Flag1, Flag2, Flag3
// remove flag
value &= ~MyEnum.Flag2; //value is now Flag1, Flag3
Le enumerazioni possono avere valori inaspettati
Poiché un enum può essere lanciato su e dal suo tipo integrale sottostante, il valore potrebbe non rientrare nell'intervallo di valori indicato nella definizione del tipo enum.
Sebbene il tipo di DaysOfWeek
seguente DaysOfWeek
abbia solo 7 valori definiti, può comunque contenere qualsiasi valore int
.
public enum DaysOfWeek
{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7
}
DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(d); // prints 31
DaysOFWeek s = DaysOfWeek.Sunday;
s++; // No error
Attualmente non esiste un modo per definire un enum che non abbia questo comportamento.
Tuttavia, i valori di enum non definiti possono essere rilevati utilizzando il metodo Enum.IsDefined
. Per esempio,
DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(Enum.IsDefined(typeof(DaysOfWeek),d)); // prints False