1. Wprowadzenie
Wyobraź sobie, że jesteś baristą w popularnej kawiarni. Przychodzi do ciebie klient i podaje jeden z pięciu ulubionych napojów. Nie robisz filozoficznej analizy, tylko szybko patrzysz w menu i reagujesz: „Cappuccino? Jasne! Oto twoje cappuccino!”. Gdybyś każdą pozycję sprawdzał przez osobny if, twój kod wyglądałby jak stos kubków po lunchowym szczycie — nieporęczny i niezbyt wygodny.
Operator switch pozwala elegancko sprawdzać wartość zmiennej i wykonywać różne akcje w zależności od wyniku. Działa tylko z określonymi typami danych (o tym za chwilę), ale w większości menu użytkownika, prostych komend czy rozpoznawaniu statusów to idealne narzędzie.
2. Składnia klasycznego switch w C#
Oto minimalny schemat blokowy działania:
switch (Wyrażenie) {
case Wartość1:
// akcje
break;
case Wartość2:
// akcje
break;
...
default:
// akcje domyślne
break;
}
Przykład 1: klasyczne menu
Console.WriteLine("Wybierz napój: 1 - Kawa, 2 - Herbata, 3 - Kakao");
string input = Console.ReadLine();
int choice = int.Parse(input);
switch (choice)
{
case 1:
Console.WriteLine("Wybrałeś kawę. Świetny wybór!");
break;
case 2:
Console.WriteLine("Herbata — też spoko.");
break;
case 3:
Console.WriteLine("Kakao — dla miłośników przytulności!");
break;
default:
Console.WriteLine("Nie ma takiego napoju w menu.");
break;
}
- Blok switch sprawdza choice pod kątem równości z wartościami po case.
- Po każdej opcji koniecznie piszemy break; — inaczej wykonanie przejdzie do następnego case (o tym za chwilę).
- Blok default — jak else; zadziała, jeśli żaden case nie pasuje.
Jak działa switch w środku? — Krok po kroku
- Najpierw obliczane jest wyrażenie w nawiasach po switch (w naszym przykładzie — zmienna choice).
- Program porównuje je po kolei z każdą podaną wartością (case).
- Jeśli pasuje — wykonywane są instrukcje tego bloku. Potem napotyka break i program wychodzi z bloku switch.
- Jeśli nie pasuje do żadnego case, wykonywany jest blok default (jeśli jest).
Schemat wizualny
| Wartość zmiennej | case 1 | case 2 | case 3 | default |
|---|---|---|---|---|
| 1 | + | |||
| 2 | + | |||
| 3 | + | |||
| inne | + |
„+” — ten blok się wykonuje
3. Jakie typy obsługuje klasyczny switch?
W klasycznej składni (czyli bez "Pattern Matching" i nowych bajerów, o których pogadamy później!) switch obsługuje:
- Proste typy całkowite (int, byte, char, long, short, sbyte, ushort, uint, ulong)
- Stringi (string)
- Wyliczenia (enum)
- Znaki (char)
Przykład 2: przełączanie po stringach
Console.WriteLine("Wybierz komendę: start, stop, pause");
string command = Console.ReadLine();
switch (command)
{
case "start":
Console.WriteLine("Program uruchomiony!");
break;
case "stop":
Console.WriteLine("Program zatrzymany.");
break;
case "pause":
Console.WriteLine("Program wstrzymany.");
break;
default:
Console.WriteLine("Nieznana komenda.");
break;
}
4. Po co jest break i co się stanie, jeśli go zapomnisz?
Najpopularniejszy błąd programistyczny wśród początkujących — zapomnieć break; w case. Zobaczmy, co się stanie, jeśli go pominiesz.
Przykład 3: wpadanie do następnego bloku (fall-through)
int day = 2;
switch (day)
{
case 1:
Console.WriteLine("Poniedziałek");
break;
case 2:
Console.WriteLine("Wtorek");
case 3:
Console.WriteLine("Środa");
break;
default:
Console.WriteLine("Nieznany dzień");
break;
}
Co się stanie?
- Na wejściu day = 2.
- Najpierw wykona się linia: "Wtorek"
- Nie ma break — wykonanie przejdzie od razu do case 3 i wykona: "Środa"
- Potem napotka break; — wyjście.
Na ekranie zobaczysz:
Wtorek
Środa
To typowy błąd!
- Jeśli chcesz wykonać JEDNĄ akcję, dawaj break; w każdym case.
- Jeśli (rzadko) chcesz, żeby kilka opcji wykonywało tę samą logikę, możesz je „skleić” (patrz niżej).
5. Grupowanie wartości case
Czasem kilka wartości powinno zachowywać się tak samo. Po co kopiować ten sam kod?
Przykład 4: taka sama reakcja na kilka case
char grade = 'B';
switch (grade)
{
case 'A':
case 'B':
case 'C':
Console.WriteLine("Zaliczone!");
break;
case 'D':
case 'E':
Console.WriteLine("Jest pole do poprawy.");
break;
default:
Console.WriteLine("Nieprawidłowa ocena.");
break;
}
Co się dzieje?
- Jeśli grade to 'A', 'B' lub 'C', zadziała pierwszy blok: "Zaliczone!".
- Jeśli 'D' lub 'E' — drugi blok.
- Jeśli coś innego — default.
6. Co wolno, a czego nie wolno w klasycznym switch
Można:
- Używać literałów (stałych) w case, np.: case 1:, case 'A':, case "stop":.
- Porównywać enum (wyliczenia).
- Pominąć default, ale zwykle się przydaje.
Nie można:
- Używać zmiennych w case (tylko stałe).
- Porównywać zakresów (case >= 5:, case x > 10: — tak się nie da!).
- Używać double, float i innych wartości zmiennoprzecinkowych — tylko całkowite, string, char, enum.
- Pisać kilku wartości po przecinku w jednym case (case 1, 2: tak nie rób; napisz kilka case pod rząd).
7. Cechy i typowe błędy
W prawdziwych projektach switch często używa się do menu, obsługi statusów, komend, kodów błędów i jeszcze tysiąca innych rzeczy. Ale jak każdy tool, ma swoje niuanse.
Typowe błędy:
- Pominięty break (o czym już mówiliśmy).
- Zły typ wyrażenia switch (np. próba użycia double).
- Niepasująca wielkość liter w stringach (case "Start": nie zadziała dla "start") — stringi porównywane są z uwzględnieniem wielkości liter!
- Nieobsłużona wartość (zapomniany default, użytkownik wpisał coś innego).
Pułapka z zagnieżdżonymi switchami
Chociaż taki kod się zdarza, najczęściej jest słabo czytelny. Jeśli łapiesz się na tym, że wrzucasz switch w switch, może czas wydzielić kod do osobnej metody albo użyć OOP/enum/tablicy.
GO TO FULL VERSION