Co oznacza atrybut wyliczenia [Flags] w języku C#?

Od czasu do czasu widzę wyliczenie podobne do poniższego:

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

Nie rozumiem, co dokładnie robi atrybut [Flags].

Czy ktoś ma dobre wyjaśnienie lub przykład, który mógłby opublikować?


person Brian Leahy    schedule 12.08.2008    source źródło
comment
Oprócz zaakceptowanej odpowiedzi warto również zauważyć, że VB.NET faktycznie wymaga [Flagów] - przynajmniej według chłopaków z .NET: social.msdn.microsoft.com/forums/en-US/csharplanguage/thread /   -  person Rushyo    schedule 30.07.2012
comment
Uwaga, obecnie nie jest to wymagane w VB. Zapisz zachowanie jako C# - po prostu zmienia dane wyjściowe ToString(). Uwaga, możesz także wykonać logiczne LUB W samym wyliczeniu. Bardzo fajny. Kot = 1, Pies = 2, Kot i Pies = Kot || Pies.   -  person Chalky    schedule 04.08.2015
comment
@Chalky Masz na myśli CatAndDog = Cat | Dog (logiczne LUB zamiast warunkowego), jak sądzę?   -  person DdW    schedule 12.09.2016
comment
@DdW, częściowo poprawne: | należy użyć, ale | nazywa się binarnym OR. II to logiczne OR (umożliwiające zwarcie): Przynajmniej według Microsoftu ;) msdn.microsoft.com/en-us/library/f355wky8.aspx   -  person Pieter21    schedule 01.04.2018


Odpowiedzi (13)


Atrybutu [Flags] należy używać zawsze, gdy przeliczalność reprezentuje zbiór możliwych wartości, a nie pojedynczą wartość. Takie kolekcje są często używane z operatorami bitowymi, na przykład:

var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

Pamiętaj, że atrybut [Flags] nie sam tego umożliwia — pozwala jedynie na ładną reprezentację za pomocą metody .ToString():

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }

...

var str1 = (Suits.Spades | Suits.Diamonds).ToString();
           // "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
           // "Spades, Diamonds"

Należy również zauważyć, że [Flags] nie automatycznie powoduje, że wartości wyliczeniowe są potęgami dwójki. Jeśli pominiesz wartości liczbowe, wyliczenie nie będzie działać tak, jak można by się spodziewać w operacjach bitowych, ponieważ domyślnie wartości zaczynają się od 0 i są zwiększane.

Nieprawidłowa deklaracja:

[Flags]
public enum MyColors
{
    Yellow,  // 0
    Green,   // 1
    Red,     // 2
    Blue     // 3
}

Wartości zadeklarowane w ten sposób będą następujące: Żółty = 0, Zielony = 1, Czerwony = 2, Niebieski = 3. To sprawi, że będzie ono bezużyteczne jako flagi.

Oto przykład prawidłowej deklaracji:

[Flags]
public enum MyColors
{
    Yellow = 1,
    Green = 2,
    Red = 4,
    Blue = 8
}

Aby pobrać różne wartości w swojej właściwości, można to zrobić:

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
    // Yellow is allowed...
}

lub wcześniej niż .NET 4:

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
    // Yellow is allowed...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
    // Green is allowed...
}    

Pod kołdrą

Działa to, ponieważ w wyliczeniu użyłeś potęgi dwójki. Pod okładkami wartości wyliczeniowe wyglądają następująco w postaci binarnej i zera:

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

Podobnie, gdy ustawisz właściwość AllowedColors na Czerwony, Zielony i Niebieski za pomocą binarnego operatora bitowego OR |, parametr AllowedColors wygląda następująco:

myProperties.AllowedColors: 00001110

Zatem pobierając wartość, faktycznie wykonujesz bitowe ORAZ & na wartościach:

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

Wartość Brak = 0

A jeśli chodzi o użycie 0 w twoim wyliczeniu, cytując z MSDN:

[Flags]
public enum MyColors
{
    None = 0,
    ....
}

Użyj Brak jako nazwy stałej wyliczanej flagi, której wartość wynosi zero. Nie można użyć stałej wyliczeniowej None w operacji bitowej AND do sprawdzenia flagi, ponieważ wynik zawsze wynosi zero. Można jednak przeprowadzić logiczne, a nie bitowe porównanie wartości liczbowej z wartością Brak wyliczona stała określająca, czy ustawione są jakiekolwiek bity wartości numerycznej.

Więcej informacji na temat atrybutu flags i jego użycia można znaleźć pod adresem msdn i projektowanie flag w msdn

person andynil    schedule 12.08.2008
comment
Poza tym nie rozumiem, co tak naprawdę robi atrybut Flags? Wydaje się, że jestem w stanie dobrze zdefiniować i używać wyliczenia flag bez atrybutu. Czy służy jedynie jako wskazówka, że ​​wyliczenie może być używane jako flagi? - person Oskar; 06.08.2009
comment
Sama flaga nic nie daje. Ponadto C# nie wymaga flag jako takich. Ale implementacja ToString Twojego wyliczenia używa flag, podobnie jak Enum.IsDefined, Enum.Parse itd. Spróbuj usunąć flagi i spójrz na wynik MyColor.Yellow | MójKolor.Czerwony; bez tego otrzymasz 5, z flagami otrzymasz żółty, czerwony. Niektóre inne części frameworka również używają [Flagów] (np. Serializacja XML). - person Ruben; 17.08.2009
comment
Atrybut Flags ma większy wpływ niż metoda ToString. Visual Studio używa go przynajmniej do pewnego stopnia, gdy używa Enum w projektancie. Zobacz moje pytanie tutaj: stackoverflow.com/q/15663166/1111886 - person Fr33dan; 27.03.2013
comment
Wolę używać stałych w postaci A = 1 ‹‹ 0, B = 1 ‹‹ 1, C = 1 ‹‹ 2 ... Dużo łatwiej jest czytać, rozumieć, wizualnie sprawdzać i zmieniać. - person Nick Westgate; 09.04.2013
comment
Metoda .HasFlag(Enum flag) przyjmuje parametr typu Enum, więc typ wartości powinien być opakowany, co niekorzystnie wpływa na wydajność - person Aleksei Chepovoi; 04.05.2013
comment
@AlekseiChepovoi Enum wywodzi się z klasy ValueType, co oznacza, że ​​jest traktowane jako struct w taki sam sposób jak int, float itd. - person borrrden; 24.06.2013
comment
@borrrden, kiedy przekazujemy klasę Enum (klasę definiującą metodę HasFlag), jest ona przekazywana przez referencję, tak jak ją dostałem. Przeczytałem to w CLR Jeffreya Richtera poprzez trzecie wydanie C#, rozdział Enums i Bit Flags. - person Aleksei Chepovoi; 27.06.2013
comment
@AlekseiChepovoi też mam tę książkę, więc sprawdzę. Wydaje się jednak, że stoi to w sprzeczności ze wszystkim, co wiem o C#. Każdy artykuł, jaki mogę znaleźć, mówi, że wyliczenia są obiektami wartości, które nie są przydzielane na stercie. - person borrrden; 27.06.2013
comment
@borrrden, do cholery, tak! Znalazłem to: msdn.microsoft.com/en-us/library/ system.enum.aspx - zobacz część Uwagi: Enum jest klasą bazową dla wszystkich wyliczeń w .NET Framework. oraz Wyliczenie nie dziedziczy jawnie po Enum; relacja dziedziczenia jest obsługiwana niejawnie przez kompilator. Tak więc, kiedy piszesz: public enum bla bla bla - jest to typ wartości. Ale metoda HasFlag chce, abyś dał mu instancję System.Enum, która jest klasą (typ referencyjny:) - person Aleksei Chepovoi; 28.06.2013
comment
Enum.IsDefined nie uwzględnia atrybutu FlagsAttribute. Żadne z poniższych nie zwraca prawdy, nawet z atrybutem: Żółty | Zielony, żółty, zielony, 3 - person TheXenocide; 07.12.2013
comment
twój przykład miałby więcej sensu z punktu widzenia flagi, jeśli niebieski = 2 i zielony = 3, ponieważ w końcu zielony jest kombinacją żółtego i niebieskiego - person MikeT; 11.06.2015
comment
Jeśli chcesz wykluczyć flagę z wyliczenia, użyj xor, czyli ^ w języku C#. Więc jeśli masz myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;. Możesz zrobić: myProperties.AllowedColors = myProperties.AllowedColors ^ MyColor.Blue //myProperties.AllowedColors == MyColor.Red | Mycolor.Green - person Josh Noe; 10.02.2018
comment
Szukałem, co reprezentuje 10... po kilku testach odpowiada to wartości 2 i wartości 8 lub Green | Blue. również wartości Yellow = 1, Green = 2,... 8 pomagają łatwo zrozumieć, co oznacza 9 (8+1) lub 11 (8+2+1) w porównaniu z reprezentacją przesunięcia (‹‹). - person Jaider; 26.05.2021

Możesz to również zrobić

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

Uważam, że przesuwanie bitów jest łatwiejsze niż wpisywanie 4,8,16,32 i tak dalej. Nie ma to wpływu na kod, ponieważ wszystko jest wykonywane w czasie kompilacji

person Orion Edwards    schedule 12.08.2008
comment
Jedyne, co mi się nie podoba w tych skrótach, to to, że przypadkiem zapisujesz te wyliczenia w bazie danych jako int. Następnie będziesz musiał wielokrotnie korzystać z kalkulatora, aby podczas analizy danych dowiedzieć się, jakie wartości odpowiadają jakiemu wyliczeniu. - person JeremyWeir; 14.05.2012
comment
@JeremyWeir Czy możesz wyjaśnić, czym różniłoby się to od używania 1, 2 , 4, 8, 16, ...? Również kalkulator systemu Windows 7 zawiera bity, na które można kliknąć. - person Silvermind; 27.05.2012
comment
To właśnie mam na myśli: wolę mieć pełny int w kodzie źródłowym. Jeśli w bazie danych mam kolumnę o nazwie MyEnum, która przechowuje wartość jednego z wyliczeń, a rekord zawiera 131 072, musiałbym wyciągnąć kalkulator, aby obliczyć, że odpowiada to wyliczeniu o wartości 1 ‹‹17. Zamiast po prostu zobaczyć wartość 131 072 zapisaną w źródle. - person JeremyWeir; 29.05.2012
comment
wszystko dzieje się w czasie kompilacji. Tego typu komentarz może być interesujący dla niektórych, ale wydaje mi się frustrujący, ponieważ sugeruje, że powiedzmy 20 przesunięć bitowych w czasie wykonywania będzie miało wymierny wpływ na wydajność. Procesory są bardzo dobre w przesunięciach bitowych, wyliczenia nie będą miały dowolnej liczby elementów, a to i tak nie będzie działać dla więcej niż 32 lub 64 elementów. Niezbyt istotne jako problem z wydajnością. - person jwg; 14.02.2013
comment
@jwg Zgadzam się, głupio jest zbytnio martwić się wydajnością tego w czasie wykonywania, ale mimo wszystko myślę, że miło jest wiedzieć, że nie będzie to wstawianie przesunięć bitowych w dowolnym miejscu, w którym użyjesz wyliczenia. Raczej „to miłe”, niż cokolwiek związanego z wydajnością - person Orion Edwards; 15.02.2013
comment
@JeremyWeir - Kilka bitów zostanie ustawionych w wartości wyliczenia flagi. Zatem Twoja metoda analizy danych jest niewłaściwa. Uruchom procedurę, aby przedstawić wartość całkowitą w formacie binarnym. 131,072 [D] = 0000 0000 0000 0001 0000 0000 0000 0000 [B] [32].. Po ustawieniu 17. bitu można łatwo określić wartość wyliczeniową przypisaną 1‹‹17. 0110 0011 0011 0101 0101 0011 0101 1011 [b] [32] .. wartości wyliczeniowe przypisują 1‹‹31, 1‹‹30, 1‹‹26, 1‹‹25.. itd. itd. można określić nawet bez pomocy kalkulatora... co, wątpię, byłbyś w stanie w ogóle określić bez uzyskania reprezentacji binarnej. - person Brett Caswell; 19.03.2013
comment
Wskazując również, że możesz przesunąć bity z poprzednich wartości wyliczeniowych, a nie bezpośrednio z liczb, tj. Third = Second << 1 zamiast Third = 1 << 2 - zobacz pełniejszy opis poniżej - person drzaus; 16.05.2013
comment
Podoba mi się to, ale gdy dojdziesz do górnych granic bazowego typu wyliczeniowego, kompilator nie ostrzega przed przesunięciami bitowymi, takimi jak 1 << 31 == -2147483648, 1 << 32 == 1, 1 << 33 == 2 i tak dalej. Natomiast jeśli powiesz ThirtySecond = 2147483648 dla wyliczenia typu int, kompilator zgłosi błąd. - person aaaantoine; 04.06.2014
comment
Aby dodać kolejną opcję, która jest nowa w C# 7, możesz użyć 0b1, 0b10 itd. (lub 0b00000001, jeśli chcesz, żeby wszystko było poprawnie ułożone!) - person Graham Wager; 15.03.2017

Łączenie odpowiedzi https://stackoverflow.com/a/8462/1037948 (deklaracja poprzez przesunięcie bitów) i https://stackoverflow.com/a/9117/1037948 (używając kombinacji w deklaracji) możesz przesuwać bity poprzednich wartości zamiast używać liczby. Niekoniecznie polecanie, ale po prostu wskazywanie, że można.

Zamiast:

[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,
}

Możesz zadeklarować

[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,
}

Potwierdzanie za pomocą LinqPad:

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

Prowadzi do:

None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
person drzaus    schedule 16.05.2013
comment
Kombinacje są dobrą rekomendacją, ale myślę, że połączone przesunięcie bitowe byłoby podatne na błędy kopiowania i wklejania, takie jak Dwa = Jeden ‹‹ 1, Trzy = Jeden ‹‹ 1 itd. Rosnące liczby całkowite forma 1 ‹‹ n są bezpieczniejsze, a intencja jest jaśniejsza. - person Rupert Rawnsley; 20.03.2014
comment
@RupertRawnsley, aby zacytować moją odpowiedź: › Niekoniecznie polecając to, ale po prostu wskazując, że możesz - person drzaus; 20.03.2014

Poniżej znajduje się przykład pokazujący deklarację i potencjalne zastosowanie:

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");
            }
        }
    }
}
person OJ.    schedule 12.08.2008
comment
Ten przykład działa nawet jeśli pominiesz [Flagi]. Próbuję się czegoś dowiedzieć o tej części dotyczącej flag. - person gbarry; 07.08.2019

Oprócz zaakceptowanej odpowiedzi, w C# 7 flagi wyliczeniowe można zapisać przy użyciu literałów binarnych:

[Flags]
public enum MyColors
{
    None   = 0b0000,
    Yellow = 0b0001,
    Green  = 0b0010,
    Red    = 0b0100,
    Blue   = 0b1000
}

Myślę, że to przedstawienie wyjaśnia, jak flagi działają pod okładkami.

person Thorkil Holm-Jacobsen    schedule 20.07.2017
comment
A w C# 7.2 jest to jeszcze jaśniejsze dzięki wiodący separator! 0b_0100 - person Vincenzo Petronio; 26.10.2019

zapytałem ostatnio o czymś podobnym.

Jeśli używasz flag, możesz dodać metodę rozszerzenia do wyliczeń, aby ułatwić sprawdzanie zawartych flag (szczegóły w poście)

Dzięki temu możesz:

[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,
    ...
}

Następnie możesz zrobić:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

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

Uważam, że jest to łatwiejsze do odczytania niż większość sposobów sprawdzania dołączonych flag.

person Keith    schedule 12.08.2008
comment
Zakładam, że IsSet jest metodą rozszerzenia? - person Robert MacLean; 02.06.2009
comment
Tak - przeczytaj inne pytanie, do którego linkuję, aby uzyskać szczegółowe informacje: stackoverflow.com/questions/7244 - person Keith; 02.06.2009
comment
.NET 4 dodaje do wyliczeń metodę HasFlag, dzięki czemu można wykonać opt.HasFlag( PossibleOptions.OptionOne ) bez konieczności pisania własnych rozszerzeń - person Orion Edwards; 20.07.2010
comment
Pamiętaj, że HasFlag jest znacznie wolniejszy niż wykonywanie operacji bitowych. - person Wai Ha Lee; 12.09.2018
comment
@WaiHaLee Możesz użyć metody rozszerzenia CodeJam.EnumHelper.IsFlagSet, która jest kompilowana do szybkiej wersji przy użyciu wyrażenia: github.com/rsdn/CodeJam/wiki/M_CodeJam_EnumHelper_IsFlagSet__1 - person NN_; 29.04.2019

Pracując z flagami, często deklaruję dodatkowe elementy Brak i Wszystkie. Są one pomocne przy sprawdzaniu, czy ustawione są wszystkie flagi, czy nie ustawiono żadnej flagi.

[Flags] 
enum SuitsFlags { 

    None =     0,

    Spades =   1 << 0, 
    Clubs =    1 << 1, 
    Diamonds = 1 << 2, 
    Hearts =   1 << 3,

    All =      ~(~0 << 4)

}

Stosowanie:

Spades | Clubs | Diamonds | Hearts == All  // true
Spades & Clubs == None  // true


Aktualizacja 2019–10:

Od wersji C# 7.0 można używać literałów binarnych, które są prawdopodobnie bardziej intuicyjne w czytaniu:

[Flags] 
enum SuitsFlags { 

    None =     0b0000,

    Spades =   0b0001, 
    Clubs =    0b0010, 
    Diamonds = 0b0100, 
    Hearts =   0b1000,

    All =      0b1111

}
person Jpsy    schedule 23.10.2018
comment
Tak, łącząc wszystkie odpowiedzi na tej stronie, teraz używam go regularnie, ale z wiodącym separatorem 0b_1111 - person Marcelo Scofano Diniz; 03.08.2020

@Nidonocu

Aby dodać kolejną flagę do istniejącego zestawu wartości, użyj operatora przypisania OR.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));
person steve_c    schedule 12.08.2008

Aby dodać Mode.Write:

Mode = Mode | Mode.Write;
person David Wengier    schedule 12.08.2008

Jest dla mnie coś zbyt gadatliwego w konstrukcji if ((x & y) == y)..., szczególnie jeśli x ORAZ y są złożonymi zestawami flag, a chcesz tylko wiedzieć, czy jakiekolwiek się nakładają.

W tym przypadku wszystko, co musisz wiedzieć, to czy po utworzeniu maski bitowej znajduje się wartość różna od zera[1].

[1] Zobacz komentarz Jaime'a. Gdybyśmy rzeczywiście maskowali bity, musielibyśmy jedynie sprawdzić, czy wynik był pozytywny. Ale ponieważ enums może być nawet, co dziwne, ujemne w połączeniu z atrybutem [Flags] , kodowanie != 0 zamiast > 0 jest defensywne.

Opierając się na konfiguracji @andnila...

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();
        }
    }
}
person ruffin    schedule 01.05.2013
comment
Wyliczenie może opierać się na typie ze znakiem, dlatego należy użyć != 0 zamiast >0. - person raven; 16.08.2013
comment
@JaimePardos - Dopóki zachowamy uczciwe bajty, tak jak w tym przykładzie, nie ma koncepcji ujemnej. Tylko od 0 do 255. Jak MSDN ostrzega, zachowaj ostrożność, jeśli definiujesz liczbę ujemną jako stałą flagę wyliczoną, ponieważ... [to] może sprawić, że Twój kod będzie mylący i będzie sprzyjał błędom w kodowaniu. Dziwnie jest myśleć w kategoriach negatywnych bitflagów! ;^) Za chwilę będę edytować więcej. Ale masz rację, jeśli użyjemy wartości ujemnych w naszym enum, musielibyśmy sprawdzić != 0. - person ruffin; 16.08.2013

Flagi umożliwiają użycie maskowania bitów wewnątrz wyliczenia. Umożliwia to łączenie wartości wyliczeniowych przy zachowaniu tych, które zostały określone.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}
person Jay Mooney    schedule 12.08.2008
comment
To jest niepoprawne, możesz użyć maskowania bitów, nawet jeśli wyliczenie nie jest oznaczone jako Flags. - person Shadow; 01.11.2020

Przepraszamy, jeśli ktoś już zauważył ten scenariusz. Doskonały przykład flag, które możemy zobaczyć w odbiciu. Tak Wiązanie flag ENUM .

[System.Flags]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public enum BindingFlags

Wykorzystanie

// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof (TestClass);

Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public | 
    BindingFlags.Static, null, null, new object [] {});
person kbvishnu    schedule 27.01.2020

  • Flagi są używane, gdy przeliczalna wartość reprezentuje zbiór elementów wyliczeniowych.

  • tutaj używamy operatorów bitowych, | I &

  • Przykład

                 [Flags]
                 public enum Sides { Left=0, Right=1, Top=2, Bottom=3 }
    
                 Sides leftRight = Sides.Left | Sides.Right;
                 Console.WriteLine (leftRight);//Left, Right
    
                 string stringValue = leftRight.ToString();
                 Console.WriteLine (stringValue);//Left, Right
    
                 Sides s = Sides.Left;
                 s |= Sides.Right;
                 Console.WriteLine (s);//Left, Right
    
                 s ^= Sides.Right; // Toggles Sides.Right
                 Console.WriteLine (s); //Left
    
person Mukesh Pareek    schedule 11.11.2020
comment
Twój przykład jest błędny (i nie daje oczekiwanych wyników), ponieważ prawidłowe użycie Flags wymaga, aby wartości wyliczeniowe miały ustawione unikalne bity. Powinien być co najmniej jeden ustawiony (chyba że masz pseudowartość, taką jak None). Twoje wyliczenie powinno wyglądać tak: ` wyliczenie publiczne Boki { Lewy = 1, Prawy = 2, Górny = 4, Dół = 8 } ` - person Jakob; 18.11.2020