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.