środa, 30 września 2009

Prostsze warunki czyli Flagi w C#

Używanie flag bitowych podczas programowania w dzisiejszych czasach może wydawać się śmieszne. Jednak jeśli chcemy zaoszczędzić pamięć czy też zwiększyć czytelność naszego kodu – są dla nas idealnym narzędziem.
Cała sprawa sprowadza się do używania bitowych operatorów | (OR), & (AND) oraz ^(XOR). Prosty przykład:
[Flags]
        enum Imiona
        {
            Nic = 0,
            Malgosia = 1,
            Marysia = 2,
            Stefan = 4,
            Ferdek = 16,
            Pawel = 32,
            Sebastian = 64
        };
Elementy zostały specjalnie oznaczone jako kolejne potęgi 2. Dlaczego? Zobaczymy to w poniższym przykładzie:
Imiona imiona = Imiona.Malgosia | Imiona.Marysia | Imiona.Stefan |         
 Imiona.Ferdek | Imiona.Pawel | Imiona.Sebastian;

Console.WriteLine(imiona);

Po uruchomieniu programu na ekranie zobaczymy wydruk wszystkich imion oprócz „Nic”. Korzystamu tutaj z operacji bitowej sumy logicznej OR. Elementy naszego typu wyliczeniowego możemy przedstawić w postaci liczb binarnych:
000000 - Nic
000001 - Malgosia
000010 - Marysia
000100 - Stefan
001000 - Ferdek
010000 - Pawel
100000 – Sebastian

Suma logiczna na tych elementach daje nam następujący rezultat
111111
Ponieważ w naszym typie wyliczeniowym nie ma takiego elementu zostaną wykorzystane kolejno pokazane wzorce:
000001
000010
000100
001000
010000
100000

Jeśli chcielibyśmy np. mieć element odpowiadający Stefanowi i Malgosi, wytarczy że obliczymi ich sumę logiczną:
000001 - Malgosia
000100 - Stefan
000101 - StefanMalgosia – dziesiętnie 5

enum Imiona
        {
            Nic = 0,
            Malgosia = 1,
            Marysia = 2,
            Stefan = 4,
            StefanMalgosia = 5,
            Ferdek = 16,
            Pawel = 32,
            Sebastian = 64
        };

            Imiona imiona = Imiona.Stefan | Imiona.Malgosia;
            Console.WriteLine(imiona);
W wyniku działania programu otrzymamy wynik StefanMalgosia.

Odpinanie flag od naszej zmiennej imiona jest bardzo proste. Aby od naszego przykładu:
Imiona imiona = Imiona.Stefan | Imiona.Malgosia;
            Console.WriteLine(imiona);
odpiąć Stefana wystarczy zastosować konstrukcję:
imiona &= Imiona.Malgosia;
            Console.WriteLine(imiona);

            //lub po prosu:
            imiona &= ~Imiona.Stefan;
            Console.WriteLine(imiona);

Odpowiada to konstrukcją:
101
001
001

101
011
001

Jak więc widać posługiwanie się flagami jest niezwykle proste. Flagi bitowe można spotkać podczas codziennego programowania w WindowsForms. Przykładem jest typ wyliczeniowy Anchor którego definicja wygląda następująco:
[Flags]
    [Editor("System.Windows.Forms.Design.AnchorEditor, 
System.Design, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
    public enum AnchorStyles
    {
        None = 0,
        Top = 1,
        Bottom = 2,
        Left = 4,
        Right = 8,
    }
Jeszcze może odnośnie występowania tutaj elemenu None (u mnie nic). Jest to zalecany sposób tworzenia typów wyliczeniowych. Jeśli nie podamy w sposób jawny numerów poszczególnych elementów w naszym Enum-ie, to zgodnie z dokumentacją nasz typ wyliczeniowy rozpocznie się od 0 i będzie przyjmował kolejne liczby z typu int.

To by było na tyle o stosowaniu flag. Mam nadzieję że chociaż trochę się przekonacie do ich stosowania.

Brak komentarzy:

Prześlij komentarz