Podczas pisania aplikacji zdarzają nam się obiekty, które mają jakiś swój specyficzny rodzaj. Część z tych problemów można rozwiązać poprzez dziedziczenie, ale w wielu przypadkach będzie to przerost formy nad treścią, a samo zapisanie później danych do bazy będzie rodziło wiele problemów i obciążeń. Z pomocą w tym przypadku przychodzi nam typ wyliczeniowy.

Załóżmy, że tworzymy aplikację do zarządzania naszą biblioteczką. Każda książka ma swoje umiejscowienie (półka, szafa, biurko, inne) i informację o statusie jej posiadania (chcę mieć, zamówiona, posiadana, pożyczona). Można to zrobić na kilka sposobów:

Sposób 1:

Utworzenie zmiennych typu string:

I teraz ustawienie statusu:

Zawsze problemem jest string, bo bardzo łatwo o literówki. Jeśli ktoś dostanie nasz kod i będzie chciał coś dopisać, to może potraktować nasz status fizyczny egzemplarza i wpisać, że książka jest uszkodzona. Z kolei baza danych musi przechowywać sporo informacji. Problem ten można rozwiązać w inny sposób.

Sposób 2:

Przechowywanie statusów jako liczby:

I teraz ustawienie statusu:

Ok, problem literówek mamy już rozwiązany, a baza danych przechowuje małe liczby całkowite, więc też jest to dobre rozwiązanie. Tylko co oznacza to 3? W chwili pisania kodu ustalę sobie, że 3 to książka posiadana. Za tydzień będę o tym pamiętał? A za pół roku? Jak wstawię komentarz to czy będę o nim pamiętał, chciało mi się szukać lub nie usunę go przypadkiem/nie dokonam edycji?

Sposób 3:

Z pomocą przychodzi nam typ wyliczeniowy. Po pierwsze deklarujemy go. W tym celu tworzymy nowy plik .cs i podobnie jak tworząc klasę wpisujemy:

Teraz w klasie Ksiazka typem statusów będzie odpowiedni typ utworzony powyżej:

Teraz ustawimy status i umiejscowienie:

Teraz jest czytelnie i nie potrzebujemy żadnych komentarzy. Jeśli sąsiad za pół roku, a my za rok będziemy coś dopisywać, to nie ustawimy innego statusu niż jeden z wymienionych. Kolejną zaletą typu wyliczeniowego jest możliwość rzutowania na liczbę całkowitą.

Zapis i odczyt danych z/do bazy zrealizujemy poprzez rzutowanie na int i z powrotem:

Z automatu mamy załatwioną optymalizację przechowywanych danych, bo zapisujemy tylko proste integery. W banalny sposób można też odczytać dane i wrzucić je do obiektu.
Można też ustawić konkretną liczbę, która będzie reprezentować dany typ:

W tym przypadku biurko zostanie zamienione na liczbę 5, a inne na kolejną, czyli 6. Zawsze domyślną wartością pierwszego elementu jest 0, dlatego półka to 0, a szafka jest reprezentowana przez 1.

Polecam korzystanie z tego rozwiązania, bo naprawdę sporo ułatwia i upraszcza nasz kod. Sam miałem problemy ze zrozumieniem tego na początku, ale jak doczytałem dokumentację, wszystko stało się jasne i teraz każda moja aplikacja posiada sporo enumów 🙂