C# Language Enum come bandiere


Esempio

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