enum - c# flags combine




Was bedeutet das Aufzählungsattribut[Flags] in C#? (7)

Über das Konstrukt if ((x & y) == y)... ist etwas übermäßig wortreich, besonders wenn x UND y beide zusammengesetzte Flags sind und man nur wissen will, ob es Überlappungen gibt.

In diesem Fall müssen Sie nur wissen, ob nach der Bitmaskierung ein Wert ungleich Null [1] vorliegt .

[1] Siehe Jaimes Kommentar. Wenn wir authentisch Bitmasken hätten , müssten wir nur überprüfen, ob das Ergebnis positiv ist. Aber da enum s sogar negativ sein kann, ist es in Kombination mit msdn seltsam, defensiv zu codieren != 0 und nicht > 0 .

Aufbau von @ andnils Setup ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BitFlagPlay
{
    class Program
    {
        [Flags]
        public enum MyColor
        {
            Yellow = 0x01,
            Green = 0x02,
            Red = 0x04,
            Blue = 0x08
        }

        static void Main(string[] args)
        {
            var myColor = MyColor.Yellow | MyColor.Blue;
            var acceptableColors = MyColor.Yellow | MyColor.Red;

            Console.WriteLine((myColor & MyColor.Blue) != 0);     // True
            Console.WriteLine((myColor & MyColor.Red) != 0);      // False                
            Console.WriteLine((myColor & acceptableColors) != 0); // True
            // ... though only Yellow is shared.

            Console.WriteLine((myColor & MyColor.Green) != 0);    // Wait a minute... ;^D

            Console.Read();
        }
    }
}

Von Zeit zu Zeit sehe ich ein enum wie folgt:

[Flags]
public enum Options 
{
    None    = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    Option4 = 8
}

Ich verstehe nicht, was genau das [Flags] -Attribut tut.

Hat jemand eine gute Erklärung oder ein Beispiel, das er posten könnte?


@Nidonocu

Verwenden Sie den OR-Zuweisungsoperator, um einer vorhandenen Gruppe von Werten ein weiteres Flag hinzuzufügen.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));

Ich habe kürzlich nach etwas ähnlichem gefragt .

Wenn Sie Flags verwenden, können Sie enums eine Erweiterungsmethode hinzufügen, um das Überprüfen der enthaltenen Flags zu erleichtern (siehe Beitrag für Details).

Dies ermöglicht Ihnen Folgendes:

[Flags]
public enum PossibleOptions : byte
{
    None = 0,
    OptionOne = 1,
    OptionTwo = 2,
    OptionThree = 4,
    OptionFour = 8,

    //combinations can be in the enum too
    OptionOneAndTwo = OptionOne | OptionTwo,
    OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
    ...
}

Dann können Sie tun:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

if( opt.IsSet( PossibleOptions.OptionOne ) ) {
    //optionOne is one of those set
}

Ich finde das einfacher zu lesen als die meisten Möglichkeiten, die enthaltenen Flaggen zu überprüfen.


Im Folgenden finden Sie ein Beispiel, das die Deklaration und mögliche Verwendung zeigt:

namespace Flags
{
    class Program
    {
        [Flags]
        public enum MyFlags : short
        {
            Foo = 0x1,
            Bar = 0x2,
            Baz = 0x4
        }

        static void Main(string[] args)
        {
            MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;

            if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
            {
                Console.WriteLine("Item has Foo flag set");
            }
        }
    }
}

Kombiniert man die Antworten https://.com/a/8462/1037948 (Deklaration über Bit-Shifting) und https://.com/a/9117/1037948 (unter Verwendung von Deklarationskombinationen), kann man frühere Werte etwas verschieben als mit Zahlen. Ich empfehle es nicht unbedingt, aber ich kann nur darauf hinweisen, dass Sie es können.

Eher, als:

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,   // 1
    Two     = 1 << 1,   // 2
    Three   = 1 << 2,   // 4
    Four    = 1 << 3,   // 8

    // combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

Sie können deklarieren

[Flags]
public enum Options : byte
{
    None    = 0,
    One     = 1 << 0,       // 1
    // now that value 1 is available, start shifting from there
    Two     = One << 1,     // 2
    Three   = Two << 1,     // 4
    Four    = Three << 1,   // 8

    // same combinations
    OneAndTwo = One | Two,
    OneTwoAndThree = One | Two | Three,
}

Bestätigung mit LinqPad:

foreach(var e in Enum.GetValues(typeof(Options))) {
    string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}

Ergebnisse in:

None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8

Mit Flags können Sie Bitmasken in Ihrer Enumeration verwenden. Auf diese Weise können Sie Aufzählungswerte kombinieren und gleichzeitig beibehalten, welche Werte angegeben werden.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}

So fügen Sie Mode.Write :

Mode = Mode | Mode.Write;




flags