Enum z atrybutem Flags

Załóżmy, że mamy zdefiniowaną stałą listę dostępnych pół formularza: imię, nazwisko, data urodzenia, płeć.
Pola te mogą być wyświetlane w różnych konfiguracjach, np. Imię z nazwiskiem, nazwisko z datą urodzenia lub tylko płeć. Pomijając fakt że z reguły typy wyliczeniowe łamią zasadę Open/Closed principle (http://pl.wikipedia.org/wiki/Zasada_otwarte-zamkni%C4%99te) i zastosowanie ich w tym przypadku może nie jest najlepszym pomysłem, to jednak chcąc pokazać jak zachowuje się typ Enum oznaczony atrybutem Flags pokuszę się o przygotowanie właśnie takiego przykładu.

    [Flags]
    public enum FieldType
    {
        None, //0000
        FirstName, //0001
        LastName, //0010
        DateOfBirth, //0100
        Gender //1000
    }

Ze względu na atrybut Flags, każda wartość typu wyliczeniowego odzwierciedla teraz flagę w postaci binarnej. Dzięki temu możemy posłużyć się bitowym operatorem OR (suma logiczna), w celu definicji jakie pola mają się pokazywać na formularzu, oraz AND (iloczyn logiczny) w celu określenia jakie flagi zostały wykorzystane.

Poniższy przykład definiuje pola imię, nazwisko i data urodzenia. Binarnie kombinacja tych flag przedstawia się jako: 0111.

DisplayHelper.Display(FieldType.FirstName | FieldType.LastName | FieldType.DateOfBirth);

Chcąc określić jakie flagi zostały wykorzystane, stosujemy operator AND.

    public class DisplayHelper
    {
        public static void Display(FieldType fieldType)
        {
            if (DetermineFieldType(fieldType, FieldType.FirstName))
                Console.WriteLine("Display First name field");

            if (DetermineFieldType(fieldType, FieldType.LastName))
                Console.WriteLine("Display Last name field");

            if (DetermineFieldType(fieldType, FieldType.DateOfBirth))
                Console.WriteLine("Display Date of birth field");

            if (DetermineFieldType(fieldType, FieldType.Gender))
                Console.WriteLine("Display gender field");
        }

        private static bool DetermineFieldType(FieldType fieldType, FieldType compareTo)
        {
            return (fieldType & compareTo) == compareTo;
        }
    }

W metodzie DetermineFieldType wykonywana jest operacja iloczynu logicznego (AND).
Chcąc określić, czy flaga 0111 (odpowiadająca zastosowaniu trzech typów: FirstName, LastName i DateOfBirth), przekazana jako parametr wywołania metody Display, zawiera w sobie np. pole FirstName, wykonywana jest operacja iloczynu logicznego (0111 AND 0001) = 0001, która potwierdza, że typ FirstName (0001) ma zostać wyświetlony na formularzu.

W .NET 4.0. do tego celu można wykorzystać metodę HasFlag() i metoda ta wygląda wówczas w ten sposób

        private static bool DetermineFieldType(FieldType fieldType, FieldType compareTo)
        {
            return fieldType.HasFlag(compareTo);
        }
Advertisements

5 thoughts on “Enum z atrybutem Flags

  1. Od frameworka 4 nawet nie trzeba stosować operatora AND. Wystarczy fieldType.HasFlag(FieldType.Gender)

  2. Jeżeli się nie mylę to konwencją msdn przy nazwie enumow z Flags jest nazwa w liczbie mnogiej.

  3. Bez atrybutu flags też będzie działać 🙂 Wykorzystywany jest on w celach informacyjnych, oraz przy przeciążeniu ToString()

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s