CodeGym /Kursy /C# SELF /Enumy w C#: wygodne nazwane stałe

Enumy w C#: wygodne nazwane stałe

C# SELF
Poziom 10, Lekcja 4
Dostępny

1. Wprowadzenie

W programowaniu często trzeba operować listami z góry znanych, ograniczonych opcji. Na przykład: dni tygodnia, kolory świateł drogowych, poziomy trudności gry, statusy zamówienia. Każda z tych opcji to zwykle stała wartość. I tu właśnie dochodzimy do naszego dzisiejszego tematu — enumów (enum).

Enum — to specjalny typ danych, który pozwala zadeklarować zestaw nazwanych stałych.
enum — jak pudełko z przegródkami i naklejkami, gdzie każda naklejka to unikalna nazwa powiązana z liczbą.

  • Twój kod staje się czytelny i samoopisujący się;
  • Zamiast tajemniczych „magicznych liczb” typu 0, 1, 2 pojawiają się wyraziste nazwy: DayOfWeek.Monday albo TrafficLight.Red;
  • Kompilator się obrazi, jeśli spróbujesz przypisać niepoprawną wartość;
  • Za każdym elementem kryje się... zwykła liczba całkowita! (Ale do tego jeszcze wrócimy.)

2. Składnia deklaracji enumów

Zróbmy pierwszy enum — typy pogody do naszej przyszłej apki. Tak to wygląda:


// Enum warunków pogodowych
public enum WeatherCondition
{
    Sunny,       // 0
    Cloudy,      // 1
    Rainy,       // 2
    Stormy,      // 3
    Snowy        // 4
}
Deklaracja enum WeatherCondition
  • Słowo kluczowe enum definiuje nowy typ.
  • W klamrach — nazwy opcji. Domyślnie każda opcja dostaje liczbę całkowitą, zaczynając od zera (Sunny == 0, Cloudy == 1 itd.).
  • Możesz jawnie ustawić wartości:
public enum WeatherCondition
{
    Sunny = 1,
    Cloudy = 2,
    Rainy = 4,
    Stormy = 8,
    Snowy = 16
}

To wygodne, jeśli wartości mają odpowiadać jakimś zewnętrznym standardom albo protokołom.

3. Użycie enumów

Wyobraź sobie, że napisaliśmy apkę — mały program konsolowy, który reaguje na pogodę.

// Klasa aplikacji
class Program
{
    static void Main()
    {
        // Używamy naszego enum do przechowywania stanu pogody
        WeatherCondition todayWeather = WeatherCondition.Sunny;

        // Wyświetlamy na ekranie
        Console.WriteLine($"Dzisiaj pogoda: {todayWeather} ({(int)todayWeather})");

        // A teraz zasymulujemy zmianę pogody
        todayWeather = WeatherCondition.Rainy;
        Console.WriteLine($"Oj! Pogoda się zmieniła: {todayWeather} ({(int)todayWeather})");
    }
}

Co się stanie?


Dzisiaj pogoda: Sunny (0)
Oj! Pogoda się zmieniła: Rainy (2)
  • todayWeather — to nie string, nie liczba, tylko element enum.
  • Rzutowanie na (int) pozwala zobaczyć „liczbowy” kod tej wartości.

Enumy świetnie współpracują z warunkami:

if (todayWeather == WeatherCondition.Rainy)
    Console.WriteLine("Weź parasol!");

4. Praktyczne scenariusze użycia enum

Gdzie spotkasz enumy?

  • W aplikacjach biznesowych: statusy zamówień (New, Processing, Shipped, Cancelled).
  • W systemach zarządzania użytkownikami: poziomy dostępu (User, Moderator, Admin).
  • W grach: stany postaci (Idle, Moving, Jumping, Falling).
  • W GUI: przyciski, komunikaty, kolory ikonek.

A jeśli wejdziesz głębiej w .NET — znajdziesz je praktycznie w co drugim klasie standardowej biblioteki! Na przykład operacje na plikach mają enumy do określania trybu otwarcia pliku (czytanie, zapis, tworzenie).

5. Jawne wartości i zakres wartości

Czasem chcesz przekonwertować zestaw int używanych w kodzie na enum. To bardzo proste:


public enum CompassDirection
{
    North = 10,
    East = 20,
    South = 30,
    West = 40
}
Enum z jawnymi wartościami

Teraz CompassDirection.North = 10, East = 20 itd. Jeśli jakiś element nie ma jawnie podanej wartości, dostaje automatycznie +1 względem poprzedniego.

Typ przechowywania

Domyślnie enum jest przechowywany jako int (4-bajtowa liczba całkowita). Ale możesz podać swój typ bazowy, jeśli chcesz oszczędzić pamięć:

public enum TinyEnum : byte
{
    First,  // 0
    Second, // 1
    Third   // 2
}

Teraz każda wartość enum to tylko jeden bajt!

Pełna lista możliwych typów: byte, sbyte, short, ushort, int, uint, long, ulong.

6. Konwersja między enum a liczbami/stringami

Konwersja enum ↔ int:

Żeby przekonwertować enum na int i odwrotnie, po prostu użyj rzutowania:

WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // Dostaniemy 1

WeatherCondition fromNumber = (WeatherCondition)2; // Dostaniemy Rainy

Konwersja enum ↔ string:

Enum na string? Wystarczy wywołać metodę ToString().

// Konwertujemy enum na string
string name = WeatherCondition.Stormy.ToString(); // "Stormy"

// Konwertujemy string na enum przez Enum.Parse
WeatherCondition parsed = (WeatherCondition)Enum.Parse(typeof(WeatherCondition), "Stormy");

// Można też użyć Enum.TryParse
WeatherCondition parsedOk;
if (Enum.TryParse("Snowy", out parsedOk))
{
    Console.WriteLine(parsedOk); // Snowy
}

Typowy błąd:
Jeśli zrzutujesz liczbę na enum, dla której nie ma takiego członka, kompilator się nie obrazi, ale dostaniesz „wirtualny” stan.
Na przykład:

WeatherCondition weird = (WeatherCondition)999;
Console.WriteLine(weird); // 999 (nie zamieni się w "Unknown"!)

Czyli programista musi uważać przy takich konwersjach.

7. switch i enum są dla siebie stworzone

Enumy (enum) świetnie współpracują z operatorem switch. To wygodny i czytelny sposób na „reagowanie” na różne wartości enum — bez długich „if-else”.

Przykład: reakcja na pogodę

public enum WeatherCondition
{
    Sunny,
    Cloudy,
    Rainy,
    Stormy,
    Snowy
}

WeatherCondition today = WeatherCondition.Rainy;

switch (today)
{
    case WeatherCondition.Sunny:
        Console.WriteLine("Słonecznie! Można iść na spacer.");
        break;
    case WeatherCondition.Cloudy:
        Console.WriteLine("Pochmurno. Możesz wziąć bluzę.");
        break;
    case WeatherCondition.Rainy:
        Console.WriteLine("Pada deszcz. Nie zapomnij parasola!");
        break;
    case WeatherCondition.Stormy:
        Console.WriteLine("Burza! Lepiej zostań w domu.");
        break;
    case WeatherCondition.Snowy:
        Console.WriteLine("Pada śnieg — załóż czapkę!");
        break;
    default:
        Console.WriteLine("Nieznana pogoda...");
        break;
}
  • Każdy przypadek (case) odpowiada jednej wartości enum.
  • Jeśli wartość nie pasuje do żadnej znanej opcji, wykona się default (przydatne, jeśli do zmiennej trafi coś niespodziewanego).

Dlaczego połączenie enum + switch jest super?

  • Kod jest czytelny: wszystkie możliwe opcje widać od razu po liście case.
  • Łatwo rozbudować: dodajesz nowy typ pogody — po prostu dodaj kolejny case.
  • Bezpieczeństwo: kompilator ostrzeże, jeśli zapomnisz obsłużyć wszystkie opcje (od C# 8.0 można nawet włączyć sprawdzanie kompletności).

Przykład: enum z logiką do gry

public enum GameState
{
    Start,
    Playing,
    Paused,
    GameOver
}

void PrintState(GameState state)
{
    switch (state)
    {
        case GameState.Start:
            Console.WriteLine("Witamy w grze!");
            break;
        case GameState.Playing:
            Console.WriteLine("Gra trwa. Powodzenia!");
            break;
        case GameState.Paused:
            Console.WriteLine("Pauza. Możesz odpocząć.");
            break;
        case GameState.GameOver:
            Console.WriteLine("Koniec gry. Spróbuj ponownie!");
            break;
        default:
            Console.WriteLine("Nieznany stan gry.");
            break;
    }
}

Tipy:

  • Jeśli masz dużo podobnych akcji dla kilku opcji, możesz je połączyć:
switch (today)
{
    case WeatherCondition.Rainy:
    case WeatherCondition.Stormy:
        Console.WriteLine("Nie zapomnij parasola i cieplejszych ciuchów!");
        break;
}
  • Nie zapominaj o default, żeby obsłużyć niespodziewane wartości (np. jeśli ktoś zrzutuje liczbę na enum bezpośrednio).
  • Ze switch łatwo budować „maszyny stanów”, menu i wszelkie systemy z ograniczonym zestawem opcji.

8. Enumy i podstawowe metody/usługi .NET

.NET daje masę przydatnych metod do enumów:

  • Enum.GetNames(typeof(WeatherCondition)) — pobierz wszystkie nazwy.
  • Enum.GetValues(typeof(WeatherCondition)) — wszystkie wartości.
  • Enum.IsDefined(typeof(WeatherCondition), "Rainy") — sprawdź, czy taki członek istnieje w enumie.
  • Dokumentacja: System.Enum

Przykład wypisania wszystkich opcji pogody:

foreach (var name in Enum.GetNames(typeof(WeatherCondition)))
{
    Console.WriteLine(name);
}

9. Częste błędy i „pułapki”

  • Używanie „magicznych liczb” zamiast enumów, przez co kod traci czytelność.
  • Brak obsługi wartości, które nie są zdefiniowane w enumie (patrz przypadek z rzutowaniem liczby).
  • Nazywanie elementów enumów bez sensu (Value1, Value2... — i już nikt nie pamięta, o co chodziło).
  • Łamanie zasady pojedynczej odpowiedzialności — używanie jednego enum do różnych rzeczy naraz.

Najlepsze rozwiązanie: zawsze używaj enumów, gdy masz skończony zestaw opcji, i dawaj elementom sensowne, samoopisujące się nazwy.

2
Zadanie
C# SELF, poziom 10, lekcja 4
Niedostępne
Użycie wyliczenia do zarządzania ustawieniami
Użycie wyliczenia do zarządzania ustawieniami
2
Zadanie
C# SELF, poziom 10, lekcja 4
Niedostępne
Aplikacja do prognozy pogody z użyciem switch
Aplikacja do prognozy pogody z użyciem switch
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION