Rozdział 11. Typy wyliczeniowe w C#

> Dodaj do ulubionych

Ta nazwa brzmi niezwykle. Jeśli ktoś kiedyś spyta was, czego się dziś nauczyliście, to powiedzcie — „Dziś nauczyliśmy się używać typów wyliczeniowych”, a na pewno mu lub jej zaimponujecie. Chyba że ta osoba zna się na programowaniu. To wtedy tylko odpowie — „Aaa, czyli ponumerowałeś parę stanów”.

11.1. Wyliczenia i stany

Słowo wyliczeniowy brzmi efektownie. Wystarczy jednak zamienić je na „ponumerowany” i od razu traci swój wyjątkowy urok. Aby zrozumieć, o co chodzi z tymi wyliczeniami, musimy znać jakiś problem, który za ich pomocą można rozwiązać.

Wiemy już, że do przechowywania wartości całkowitoliczbowych służy typ int. Do przechowywania wartości typu prawda i fałsz służą zmienne typu bool. Czasami jednak potrzebujemy miejsca do zapisania pewnego zakresu wartości lub stanów.

Przykładowe stany

Typy wyliczeniowe bardzo ułatwiają przechowywanie informacji o stanie. Stany to coś innego niż takie informacje, jak nazwisko klienta czy saldo rachunku.

Jeśli na przykład postanowię zaprogramować grę w statki (w której rysuje się prostokątne okręty różnego typu, a potem stara się zniszczyć jednostki rywala), to mogę zdecydować, że wybrany kwadrat może zawierać jeden z następujących obiektów:

  • Puste morze
  • Zaatakowany
  • Okręt wojenny
  • Krążownik
  • Łódź podwodna
  • Łódka wiosłowa

Można powiedzieć, że w ten sposób zbieram dodatkowe metadane — postanowiłem monitorować morze, a następnie dokładnie określiłem, co w danym miejscu mogę umieścić. Gdybym chciał, mógłbym ponumerować poszczególne typy obiektów:

  • Puste morze = 1
  • Zaatakowany = 2
  • Okręt wojenny = 3
  • Krążownik = 4
  • Łódź podwodna = 5
  • Łódka wiosłowa = 6

Wtedy musiałbym jednak samodzielnie monitorować te wartości i pamiętać, że jeśli gdziekolwiek na morzu użyję wartości 7, to popełnię błąd.

W języku C# istnieje specjalna konstrukcja umożliwiająca utworzenie typu zawierającego konkretny zbiór dopuszczalnych wartości. Typy takie nazywają się typami wyliczeniowymi.

enum SeaState
{
    EmptySea, Attacked, Battleship, Cruiser, Submarine, RowingBoat
};

Utworzyłem typ o nazwie SeaState, przy użyciu którego mogę przechowywać stan określonej części morza. Może on przyjmować tylko wartości określone powyżej i może być używany wyłącznie w odniesieniu do tych nazwanych wartości wyliczenia. Na przykład muszę napisać tak:

SeaState openSea;
openSea = SeaState.EmptySea;

Moja zmienna openSea może przechowywać wyłącznie wartości reprezentujące stan zawartości kawałka morza. Oczywiście C# będzie reprezentować te stany za pomocą wartości liczbowych, ale sposób, w jaki to robi, nie jest moim problemem.

Zwróć uwagę, że typy tworzone przeze mnie (np. SeaState) na listingach są oznaczone innym kolorem niż prawdziwe słowa kluczowe.

W ten sposób edytor podpowiada, że są to dodatkowe typy utworzone przez programistę i można przy ich użyciu tworzyć zmienne, ale w odróżnieniu od słów kluczowych nie należą one do języka C#. Skup się, aby na pewno dobrze zrozumieć to, o czym tu mowa. Wcześniej używaliśmy typów należących do C#, takich jak int i double. Teraz stworzyliśmy własny typ danych, przy użyciu którego możemy przechowywać dane potrzebne nam w naszej aplikacji.

11.2. Typy wyliczeniowe — tworzenie

Słowo kluczowe enum umożliwia utworzenie nowego typu, nie znajdującego się wewnątrz klasy, którego będę mógł używać we wszystkich swoich programach:

using System;

enum TrafficLight
{
    Red, RedAmber, Green, Amber
};

class EnumDemonstration
{
    public static void Main ()
    {
        TrafficLight light; light = TrafficLight.Red;
    }
}

Przykład kodu. Wyliczenie reprezentujące sygnalizację świetlną

Jeśli kiedykolwiek będziesz szukać sposobu na przechowanie czegoś, co może przyjąć ograniczoną liczbę wartości lub stanów (np. OnSale, UnderOffer, Sold, OffTheMarket itd.), pierwszą myśl skieruj ku typom wyliczeniowym.

Złota myśl programisty: używaj typów wyliczeniowych

Typy wyliczeniowe mają to do siebie, że na ich użyciu wszyscy korzystają. Dzięki nim pisanie programu staje się łatwiejsze, a kod jest bardziej zrozumiały i bezpieczniejszy. Dlatego często z nich korzystaj.

Weźmy na przykład system bankowy. Chcemy zapisać stan elementu wraz z innymi informacjami na temat klienta. Powiedzmy, że w banku tym używany jest następujący zestaw możliwych stanów konta: Zawieszone, Nowe, Aktywne, Zamknięte i W trakcie kontroli. Do przechowywania takich wartości idealnie nadaje się właśnie typ wyliczeniowy.

enum AccountState
{
    Nowe, Aktywne, WTrakcieKontroli, Zawieszone, Zamknięte
};

W ten sposób uzyskaliśmy zmienną do przechowywania informacji na temat stanu konta bankowego. Każde konto będzie zawierało zmienną typu AccountState reprezentującą jego stan.

Autor: Rob Miles

Tłumaczenie: Joanna Liana