C# Language Enum comme drapeaux


Exemple

Le FlagsAttribute peut être appliqué à un enum modifiant le comportement du ToString() pour correspondre à la nature de l'énumération:

[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);

Étant FlagsAttribute que FlagsAttribute s'appuie sur les constantes d'énumération pour avoir deux puissances (ou leurs combinaisons) et que les valeurs d'énumération sont finalement des valeurs numériques, vous êtes limité par la taille du type numérique sous-jacent. Le plus grand type numérique disponible que vous pouvez utiliser est UInt64 , qui vous permet de spécifier 64 constantes enum distinctes (non combinées). Le mot clé enum utilise par défaut le type sous-jacent int , à savoir Int32 . Le compilateur autorisera la déclaration de valeurs supérieures à 32 bits. Ceux-ci se dérouleront sans avertissement et aboutiront à deux ou plusieurs membres de la même valeur. Par conséquent, si un enum est destiné à accueillir un ensemble de bits de plus de 32 indicateurs, vous devez spécifier explicitement un type plus grand:

public enum BigEnum : ulong
{
    BigValue = 1 << 63
}

Bien que les drapeaux ne représentent souvent qu'un seul bit, ils peuvent être combinés en «ensembles» nommés pour une utilisation plus facile.

[Flags]
enum FlagsEnum
{
    None = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
       
    Default = Option1 | Option3,
    All = Option1 | Option2 | Option3,
}

Pour éviter d'épeler les valeurs décimales des puissances de deux, l' opérateur de décalage à gauche (<<) peut également être utilisé pour déclarer le même enum

[Flags]
enum FlagsEnum
{
    None = 0,
    Option1 = 1 << 0,
    Option2 = 1 << 1,
    Option3 = 1 << 2,
       
    Default = Option1 | Option3,
    All = Option1 | Option2 | Option3,
}

A partir de C # 7.0, les littéraux binaires peuvent aussi être utilisés.

Pour vérifier si la valeur de la variable enum a un certain drapeau, la méthode HasFlag peut être utilisée. Disons que nous avons

[Flags]
enum MyEnum
{
    One = 1,
    Two = 2,
    Three = 4
}

Et une value

var value = MyEnum.One | MyEnum.Two;

Avec HasFlag nous pouvons vérifier si l'un des indicateurs est défini

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

Nous pouvons également parcourir toutes les valeurs de enum pour obtenir tous les indicateurs définis

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

Ou

foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))
{
    if(value.HasFlag(flagToCheck))
    {
         Console.WriteLine("Enum has " + flagToCheck);
    }
}

Les trois exemples vont imprimer:

Enum has One
Enum has Two