sibiz.pl

Instrukcja `switch` w C#: Potężny odpowiednik `select case`

Cezary Michalak.

30 kwietnia 2026

Schemat blokowy przedstawia logikę select case c. Rozpoczyna się od wyrażenia, a następnie sprawdza kolejne stałe, wykonując odpowiednie instrukcje lub przechodząc do bloku ELSE.

Spis treści

Wielu programistów, zwłaszcza tych z doświadczeniem w językach takich jak Visual Basic, szukając w C# konstrukcji do obsługi wielokrotnych rozgałęzień, natrafia na pojęcie `select case`. Jednakże, C# nie posiada instrukcji o tej nazwie. Zamiast tego, oferuje potężniejszy i bardziej elastyczny mechanizm instrukcję switch. Ten artykuł jest kompleksowym przewodnikiem, który rozwieje wszelkie wątpliwości dotyczące `select case` w kontekście C#, pokaże, jak efektywnie korzystać z instrukcji switch, od jej podstawowych zastosowań, aż po zaawansowane techniki dostępne w nowszych wersjach języka. Zrozumienie tych mechanizmów jest kluczowe dla każdego programisty chcącego pisać czysty, czytelny i wydajny kod.

Instrukcja `switch` w C# to potężny i elastyczny odpowiednik `select case` z Visual Basic

  • W C# nie ma `select case`, jego funkcjonalność przejmuje instrukcja `switch`.
  • Podstawowa składnia `switch` wykorzystuje `case`, `break` i `default` do porównywania wartości.
  • Od C# 7.0 `switch` wspiera dopasowywanie wzorców (pattern matching) dla typów i właściwości.
  • C# 8.0 wprowadziło wyrażenia `switch` dla zwięzłego i funkcjonalnego zwracania wartości.
  • `switch` często oferuje lepszą czytelność i potencjalną optymalizację w porównaniu do `if-else` dla wielu stałych warunków.
  • Należy unikać zbyt złożonych `switch` i rozważyć refaktoryzację z użyciem polimorfizmu.

Szukasz `select case` w C#? Poznaj jego potężniejszy odpowiednik instrukcję `switch`

Jeśli trafiłeś tutaj, szukając instrukcji `select case` w C#, prawdopodobnie masz już pewne doświadczenie w programowaniu i wiesz, jak przydatne są mechanizmy warunkowego wykonywania kodu. Wielu programistów, zwłaszcza tych, którzy wcześniej pracowali z Visual Basic, intuicyjnie szuka podobnej konstrukcji w C#. Chcę Cię od razu uspokoić: w C# nie znajdziesz `select case`, ale jego funkcjonalność jest w pełni pokryta przez instrukcję switch. Co więcej, switch w C# jest znacznie bardziej rozbudowany i potężny niż jego odpowiednik w VB, oferując możliwości, o których mogłeś wcześniej nie pomyśleć. W tym artykule przeprowadzimy Cię przez wszystko, co musisz wiedzieć o instrukcji switch od podstawowych zasad działania, przez zaawansowane techniki dopasowywania wzorców, aż po nowoczesne wyrażenia switch. Po lekturze tego tekstu będziesz w stanie wykorzystać pełen potencjał tej konstrukcji w swoich projektach.

Dlaczego programiści Visual Basic mylą `select case` z `switch`?

Pomyłka między `select case` a `switch` jest bardzo częsta, zwłaszcza wśród programistów przechodzących z Visual Basic do C#. Wynika to głównie z podobnej funkcjonalności obu konstrukcji służą one do podejmowania decyzji w oparciu o wartość zmiennej. W Visual Basic, składnia `Select Case` jest intuicyjna i prosta: Select Case zmienna, a następnie kolejne bloki Case wartość. W C#, odpowiednikiem jest instrukcja switch, która ma nieco inną, choć logiczną składnię: switch (wyrażenie), a następnie bloki case wartość:. Główne punkty styczne to porównywanie jednej wartości z wieloma innymi. Jednakże, C# od samego początku kładł nacisk na inne podejście do zarządzania przepływem kodu, co zaowocowało ewolucją instrukcji switch w kierunku większej elastyczności i bezpieczeństwa, na przykład poprzez domyślne wymaganie instrukcji `break`.

Krótka historia: Odpowiednik `select case` w C# to `switch` i warto go znać

Instrukcja switch w C# jest obecna od samej pierwszej wersji języka i stanowi podstawowe narzędzie do obsługi wielokrotnych rozgałęzień warunkowych. Początkowo była ona prostym odpowiednikiem `select case`, pozwalającym na porównywanie zmiennej z zestawem stałych wartości. Jednak z każdą kolejną wersją C# jej możliwości były znacząco rozszerzane. Od prostego mechanizmu wyboru ścieżki wykonania kodu, switch ewoluował w potężne narzędzie, które potrafi analizować typy danych, dopasowywać złożone wzorce, a nawet zwracać wartości w sposób bardzo zwięzły i funkcjonalny. Zrozumienie tej ewolucji i poznanie wszystkich dostępnych funkcji switch jest kluczowe dla każdego, kto chce pisać nowoczesny i efektywny kod w C#. Zapraszam Cię do dalszej lektury, gdzie szczegółowo omówimy wszystkie aspekty tej fascynującej instrukcji.

Fundamenty instrukcji `switch`: Jak to działa w praktyce?

Instrukcja switch w C# jest fundamentalnym narzędziem do zarządzania przepływem programu, pozwalającym na wybór jednej z wielu ścieżek wykonania kodu na podstawie wartości pojedynczego wyrażenia. Działa ona na zasadzie porównywania wartości tego wyrażenia z serią predefiniowanych stałych. Kiedy znajdzie się dopasowanie, wykonywany jest blok kodu przypisany do tego konkretnego przypadku. Jest to niezwykle użyteczne, gdy musimy obsłużyć wiele różnych scenariuszy w zależności od stanu zmiennej, na przykład dnia tygodnia, statusu zamówienia czy wyboru użytkownika. Zrozumienie jej podstawowej składni i działania jest pierwszym krokiem do efektywnego wykorzystania jej potencjału.

Składnia, której potrzebujesz: `switch`, `case`, `break` i `default` krok po kroku

Podstawowa składnia instrukcji switch w C# jest prosta i logiczna. Pozwala ona na eleganckie rozdzielenie kodu na wiele ścieżek wykonania. Oto jej kluczowe elementy:

  • switch (wyrażenie): Tutaj umieszczamy zmienną lub wyrażenie, którego wartość będzie porównywana. Może to być praktycznie dowolne wyrażenie zwracające wartość, która może być porównana z wartościami w blokach case.
  • case wartość:: Każdy blok case definiuje konkretną wartość, z którą porównywane jest wyrażenie ze switch. Obsługiwane typy danych dla wartość to przede wszystkim typy całkowitoliczbowe (int, long, short, byte itp.), typy wyliczeniowe (enum) oraz typ string.
  • break;: Jest to niezwykle ważny element. Instrukcja break kończy wykonywanie bloku switch po dopasowaniu i wykonaniu kodu w danym case. Bez niej, wykonanie programu "przechodziłoby" do następnego bloku case (tzw. "fall-through"), co w C# jest zazwyczaj błędem i jest zabronione, chyba że jest to świadomie zamierzone i odpowiednio zaimplementowane (np. przez grupowanie przypadków).
  • default:: Ten opcjonalny blok jest wykonywany, jeśli żadna z wartości w blokach case nie pasuje do wartości wyrażenia w switch. Działa on jak ostatnia deska ratunku, obsługując wszystkie nieprzewidziane lub domyślne scenariusze. Nie jest obowiązkowy, ale często jest dobrym pomysłem, aby go uwzględnić.

Oto prosty przykład ilustrujący te elementy:


int dzienTygodnia = 3;
string nazwaDnia; switch (dzienTygodnia)
{ case 1: nazwaDnia = "Poniedziałek"; break; case 2: nazwaDnia = "Wtorek"; break; case 3: nazwaDnia = "Środa"; break; case 4: nazwaDnia = "Czwartek"; break; case 5: nazwaDnia = "Piątek"; break; case 6: nazwaDnia = "Sobota"; break; case 7: nazwaDnia = "Niedziela"; break; default: nazwaDnia = "Nieznany dzień"; break;
} Console.WriteLine(nazwaDnia); // Wyświetli: Środa

Praktyczne przykłady: Użycie `switch` z liczbami, stringami i typami `enum`

Instrukcja switch jest niezwykle wszechstronna i może być używana z różnymi typami danych. Oto kilka praktycznych przykładów:

1. Liczba całkowita (np. ocena, dzień tygodnia)

Jak widzieliśmy w poprzednim przykładzie, switch świetnie nadaje się do mapowania liczb na bardziej opisowe wartości.


int ocena = 4;
string opisOceny; switch (ocena)
{ case 5: opisOceny = "Bardzo dobry"; break; case 4: opisOceny = "Dobry"; break; case 3: opisOceny = "Dostateczny"; break; case 2: opisOceny = "Dopuszczający"; break; case 1: opisOceny = "Niedostateczny"; break; default: opisOceny = "Nieprawidłowa ocena"; break;
} Console.WriteLine($"Twoja ocena: {opisOceny}"); // Wyświetli: Twoja ocena: Dobry

2. String (np. komenda użytkownika, nazwa koloru)

switch może również operować na ciągach znaków, co jest przydatne do przetwarzania komend lub nazw.


string komenda = "start";
string akcja; switch (komenda.ToLower()) // Używamy ToLower() dla porównania niezależnego od wielkości liter
{ case "start": akcja = "Rozpoczynanie procesu..."; break; case "stop": akcja = "Zatrzymywanie procesu..."; break; case "restart": akcja = "Restartowanie procesu..."; break; default: akcja = "Nieznana komenda."; break;
} Console.WriteLine(akcja); // Wyświetli: Rozpoczynanie procesu...

3. Typ wyliczeniowy (enum, np. status zamówienia, poziom trudności)

Enumy i switch to para idealna. Pozwala to na bardzo czytelne zarządzanie stanami.


public enum StatusZamowienia
{ Nowe, WRealizacji, Wyslane, Dostarczone, Anulowane
} StatusZamowienia status = StatusZamowienia.Wyslane;
string opisStatusu; switch (status)
{ case StatusZamowienia.Nowe: opisStatusu = "Zamówienie oczekujące na przetworzenie."; break; case StatusZamowienia.WRealizacji: opisStatusu = "Zamówienie jest aktualnie przygotowywane."; break; case StatusZamowienia.Wyslane: opisStatusu = "Zamówienie zostało wysłane."; break; case StatusZamowienia.Dostarczone: opisStatusu = "Zamówienie dotarło do klienta."; break; case StatusZamowienia.Anulowane: opisStatusu = "Zamówienie zostało anulowane."; break; default: opisStatusu = "Nieznany status zamówienia."; break;
} Console.WriteLine(opisStatusu); // Wyświetli: Zamówienie zostało wysłane.

Kluczowa rola `break`: Dlaczego C# (zazwyczaj) nie pozwala na "przechodzenie" dalej?

W tradycyjnych instrukcjach switch w C#, po wykonaniu kodu w bloku case, program musi albo opuścić instrukcję switch (za pomocą break;, return;, throw; lub goto case), albo przejść do następnego bloku case (za pomocą goto case). Domyślnie, C# wymusza użycie break (lub innej instrukcji kończącej), aby zapobiec tzw. "fall-through" sytuacji, w której wykonanie kodu płynnie przechodzi do kolejnego case bez wyraźnego celu. Jest to mechanizm bezpieczeństwa, który ma na celu eliminację powszechnych błędów programistycznych, gdzie przypadkowe pominięcie break prowadzi do nieoczekiwanych efektów. Jednakże, C# dopuszcza świadome grupowanie przypadków, które mają wykonać ten sam kod. Robimy to, umieszczając wiele etykiet case bezpośrednio jedna po drugiej, a dopiero ostatnia z nich jest zakończona instrukcją break (lub inną instrukcją kończącą). Kod w takim przypadku jest wykonywany tylko raz, ale może być przypisany do wielu wartości.


int kod = 2;
string opisKodu; switch (kod)
{ case 1: case 2: // Oba przypadki 1 i 2 wykonają ten sam kod opisKodu = "Kod błędu niskiego priorytetu."; break; case 3: case 4: opisKodu = "Kod błędu średniego priorytetu."; break; default: opisKodu = "Nieznany kod błędu."; break;
} Console.WriteLine(opisKodu); // Wyświetli: Kod błędu niskiego priorytetu.

Nowoczesny `switch` w akcji: Czym jest i jak używać dopasowywania wzorców (Pattern Matching)?

Od wersji C# 7.0, instrukcja switch przeszła znaczącą transformację, zyskując potężne możliwości dzięki mechanizmowi dopasowywania wzorców (pattern matching). To rozszerzenie sprawia, że switch staje się znacznie bardziej elastycznym narzędziem, pozwalającym na analizę nie tylko stałych wartości, ale także typów obiektów, ich właściwości, a nawet spełnianie określonych warunków logicznych. Dzięki temu możemy pisać bardziej zwięzły i czytelny kod, który radzi sobie ze złożonymi scenariuszami w sposób, który wcześniej wymagałby skomplikowanych kaskad instrukcji if-else.

Wprowadzenie do Pattern Matching od C# 7.0: więcej niż proste porównanie

Dopasowywanie wzorców w instrukcji switch to fundamentalne rozszerzenie, które znacząco zwiększa jej możliwości. Zamiast ograniczać się do porównywania zmiennej z pojedynczymi stałymi wartościami, możemy teraz sprawdzać:

  • Typ obiektu: Czy obiekt jest instancją określonego typu?
  • Wartości właściwości/pól: Czy określone właściwości lub pola obiektu mają konkretne wartości?
  • Złożone warunki: Czy obiekt spełnia dodatkowe kryteria logiczne?

Ta elastyczność pozwala na tworzenie bardziej ekspresyjnych i łatwiejszych do zrozumienia instrukcji switch, które mogą obsługiwać szeroki zakres przypadków bez konieczności stosowania wielu zagnieżdżonych ifów.

Dopasowanie po typie: `case Typ nazwaZmiennej:`

Jednym z najprostszych, ale bardzo użytecznych wzorców jest dopasowanie po typie. Pozwala ono na sprawdzenie, czy obiekt jest instancją określonego typu, a jeśli tak, automatycznie rzutuje go do zmiennej tego typu. Jest to niezwykle wygodne, gdy pracujemy z kolekcjami obiektów różnych typów lub gdy chcemy obsłużyć różne typy danych w ramach jednej instrukcji switch.


public abstract class Figura { }
public class Kolo : Figura { public double Promien { get; set; } }
public class Kwadrat : Figura { public double Bok { get; set; } }
public class Prostokat : Figura { public double Szerokosc { get; set; } public double Wysokosc { get; set; } } Figura figura = new Kwadrat { Bok = 5 };
double pole = 0; switch (figura)
{ case Kolo k: // Dopasowanie po typie Kolo pole = Math.PI * k.Promien * k.Promien; break; case Kwadrat kw: // Dopasowanie po typie Kwadrat pole = kw.Bok * kw.Bok; break; case Prostokat p: // Dopasowanie po typie Prostokat pole = p.Szerokosc * p.Wysokosc; break; default: Console.WriteLine("Nieznany typ figury."); break;
} Console.WriteLine($"Pole figury: {pole}"); // Wyświetli: Pole figury: 25

Dodatkowe warunki z `when`: Jak dodać logikę `if` do Twojego `case`?

Słowo kluczowe when wprowadza możliwość dodania dodatkowego warunku logicznego do klauzuli case. Dzięki temu możemy tworzyć bardziej precyzyjne dopasowania, które nie tylko sprawdzają typ obiektu, ale także dodatkowe kryteria. Jest to jak połączenie mocy switch z elastycznością if.


public class Osoba { public int Wiek { get; set; } public string Imie { get; set; } } Osoba osoba = new Osoba { Imie = "Anna", Wiek = 25 };
string opisOsoby; switch (osoba)
{ case Osoba o when o.Wiek >= 18: // Dopasuj, jeśli jest typu Osoba ORAZ wiek >= 18 opisOsoby = $"{o.Imie} jest pełnoletnia."; break; case Osoba o when o.Wiek < 18: // Dopasuj, jeśli jest typu Osoba ORAZ wiek < 18 opisOsoby = $"{o.Imie} jest niepełnoletnia."; break; default: opisOsoby = "Nieznana osoba."; break;
} Console.WriteLine(opisOsoby); // Wyświetli: Anna jest pełnoletnia.

Sprawdzanie właściwości obiektu bezpośrednio w `case` (Property Pattern)

Wprowadzony w C# 8.0, wzorzec właściwości (property pattern) pozwala na dekonstrukcję obiektu i sprawdzanie jego właściwości bezpośrednio w klauzuli case. Jest to niezwykle zwięzły sposób na analizę stanu obiektu i często prowadzi do znacznie bardziej czytelnego kodu niż tradycyjne podejście z użyciem if lub dopasowania po typie z późniejszym dostępem do właściwości.


public class Produkt { public string Nazwa { get; set; } public decimal Cena { get; set; } } Produkt produkt = new Produkt { Nazwa = "Laptop", Cena = 3500.00m };
string kategoriaCeny; switch (produkt)
{ case { Cena: > 5000m }: // Dopasuj, jeśli Cena jest większa niż 5000 kategoriaCeny = "Produkt premium"; break; case { Cena: > 1000m, Nazwa: "Laptop" }: // Dopasuj, jeśli Cena > 1000 ORAZ Nazwa to "Laptop" kategoriaCeny = "Laptop ze średniej półki"; break; case { Cena: <= 1000m }: // Dopasuj, jeśli Cena jest mniejsza lub równa 1000 kategoriaCeny = "Produkt ekonomiczny"; break; default: kategoriaCeny = "Nieznana kategoria"; break;
} Console.WriteLine(kategoriaCeny); // Wyświetli: Laptop ze średniej półki

Wyrażenia `switch` (Switch Expressions): Pisz kod zwięźlej i bardziej funkcjonalnie od C# 8.0

Wersja C# 8.0 wprowadziła kolejną rewolucyjną zmianę w instrukcji switch wyrażenia switch (switch expressions). To nowa, bardziej funkcjonalna i zwięzła forma, która pozwala na zwracanie wartości bezpośrednio z instrukcji switch. Zamiast bloków kodu zakończonych break, każdy przypadek jest wyrażeniem, które przypisuje wartość do zmiennej lub jest zwracane jako wynik. Jest to znacząca zmiana, która upraszcza kod, czyni go bardziej czytelnym i eliminuje potrzebę stosowania wielu pustych bloków case.

Nowa, czytelniejsza składnia: Jak operator `=>` i `_` zmieniają zasady gry

Wyrażenia switch wprowadzają nową składnię, która jest bardziej zbliżona do deklaracji funkcji lambda. Oto kluczowe różnice:

  • Brak słowa kluczowego `switch` przed zmienną: Wyrażenie switch zaczyna się bezpośrednio od listy przypadków.
  • Operator `=>` (lambda): Zamiast dwukropka po wartości case, używamy operatora =>, który wskazuje, jaka wartość ma zostać zwrócona dla danego przypadku.
  • Znak `_` (discard pattern): Znak podkreślenia _ pełni rolę odpowiednika bloku default, przechwytując wszystkie wartości, które nie pasują do poprzednich przypadków.
  • Zwracanie wartości: Całe wyrażenie switch zwraca wartość, która może być bezpośrednio przypisana do zmiennej lub użyta w innym kontekście.

Przykład:


public enum Kierunek
{ Polnoc, Poludnie, Wschod, Zachod
} Kierunek kierunek = Kierunek.Polnoc;
string opisKierunku = kierunek switch // Wyrażenie switch
{ Kierunek.Polnoc => "Idziesz na północ.", Kierunek.Poludnie => "Idziesz na południe.", Kierunek.Wschod => "Idziesz na wschód.", Kierunek.Zachod => "Idziesz na zachód.", _ => "Nieznany kierunek." // Odpowiednik default
}; Console.WriteLine(opisKierunku); // Wyświetli: Idziesz na północ.

Koniec z `break` i `return`: Jak `switch` może zwracać wartość

Jedną z największych zalet wyrażeń switch jest to, że nie wymagają one użycia instrukcji break ani return. Całe wyrażenie switch jest traktowane jako jedna całość, która zwraca wartość. Eliminuje to potrzebę tworzenia tymczasowych zmiennych w niektórych scenariuszach i sprawia, że kod jest bardziej zwięzły i funkcjonalny. Jest to szczególnie przydatne w przypadkach, gdy potrzebujemy szybko zamapować jedną wartość na inną.

Przykład mapowania wartości:


int wynik = 75; string ocena = wynik switch
{ >= 90 => "A", >= 80 => "B", >= 70 => "C", >= 60 => "D", _ => "F"
}; Console.WriteLine($"Ocena: {ocena}"); // Wyświetli: Ocena: C

Przykłady użycia wyrażeń `switch`: Kiedy ta forma jest najlepszym wyborem?

Wyrażenia switch są idealne w sytuacjach, gdy potrzebujemy zwrócić wartość na podstawie różnych warunków. Oto kilka typowych scenariuszy:

1. Mapowanie wartości `enum` na stringi

Jak pokazano wcześniej, jest to bardzo czytelny sposób na konwersję wartości wyliczeniowych na tekstowe opisy.

2. Obliczanie wartości na podstawie różnych warunków

Możemy użyć wyrażeń switch do obliczania cen, rabatów, czy innych wartości w zależności od parametrów wejściowych.


public enum TypKlienta { Standard, Premium, VIP } decimal obliczZnizke(TypKlienta typ, decimal kwota)
{ return kwota * (typ switch { TypKlienta.Standard => 0.05m, // 5% TypKlienta.Premium => 0.10m, // 10% TypKlienta.VIP => 0.15m, // 15% _ => 0.0m });
} decimal kwotaZamowienia = 1000m;
decimal znizkaVIP = obliczZnizke(TypKlienta.VIP, kwotaZamowienia);
Console.WriteLine($"Znizka dla VIP: {znizkaVIP}"); // Wyświetli: Znizka dla VIP: 150

3. Proste transformacje danych

Wyrażenia switch mogą być używane do prostych transformacji danych, np. zwracania domyślnych wartości, parsowania danych wejściowych.


object daneWejsciowe = "123";
int? sparsowanaLiczba = daneWejsciowe switch
{ string s when int.TryParse(s, out int result) => result, int i => i, _ => null // Zwróć null, jeśli nie można sparsować
}; Console.WriteLine($"Sparowana liczba: {sparsowanaLiczba}"); // Wyświetli: Sparowana liczba: 123

Bitwa gigantów: `switch` kontra `if-else` kiedy i co wybrać?

Porównanie instrukcji switch i kaskadowych instrukcji if-else if-else jest częstym tematem dyskusji wśród programistów. Obie konstrukcje służą do wyboru ścieżki wykonania kodu, ale różnią się w sposobie działania, czytelności i potencjalnej wydajności. Wybór między nimi zależy od konkretnego scenariusza i preferencji programisty, ale istnieją pewne wytyczne, które pomagają podjąć najlepszą decyzję.

Czytelność kodu a złożoność warunków: Gdzie `switch` wygrywa?

switch zazwyczaj wygrywa pod względem czytelności, gdy mamy do czynienia z wieloma warunkami opartymi na pojedynczej zmiennej i stałych wartościach. Struktura switch jest wtedy bardziej zwarta i łatwiejsza do szybkiego zrozumienia. Widzimy wyraźnie, że jedna zmienna jest porównywana z różnymi konkretnymi wartościami. W przeciwieństwie do tego, długie kaskady if-else if mogą stać się trudne do śledzenia, zwłaszcza gdy warunki są skomplikowane lub obejmują wiele zmiennych.

switch jest również bardziej czytelny, gdy używamy go z dopasowywaniem wzorców lub wyrażeniami switch, które pozwalają na eleganckie obsługiwanie typów, właściwości czy zwracanie wartości w zwięzły sposób.

Aspekty wydajnościowe: Czy kompilator optymalizuje `switch` lepiej niż `if`?

W niektórych przypadkach, kompilator C# może zoptymalizować instrukcję switch do bardziej wydajnej struktury niż równoważne if-else if. Dotyczy to zwłaszcza sytuacji, gdy mamy do czynienia z dużą liczbą stałych przypadków. Kompilator może wtedy wygenerować tzw. tablicę skoków (jump table), która pozwala na bezpośrednie przejście do odpowiedniego bloku kodu, zamiast sekwencyjnego sprawdzania każdego warunku. W takich scenariuszach switch może być szybszy. Jednakże, dla małej liczby przypadków lub gdy warunki są dynamiczne, różnice w wydajności są zazwyczaj pomijalne, a czytelność staje się ważniejszym czynnikiem.

Sytuacje, w których `if-else` pozostaje niezastąpiony

Pomimo zalet switch, istnieją scenariusze, w których if-else jest po prostu lepszym wyborem:

  • Złożone warunki logiczne: Gdy warunki sprawdzają relacje między wieloma zmiennymi, używają operatorów logicznych (&&, ||, !), lub gdy warunki są bardzo złożone, if-else jest bardziej naturalnym i czytelnym rozwiązaniem.
  • Sprawdzanie zakresów wartości: Chociaż można to osiągnąć w switch z dopasowywaniem wzorców, tradycyjne sprawdzanie zakresów (np. if (wiek >= 18 && wiek <= 65)) jest często bardziej intuicyjne w if-else.
  • Warunki oparte na wyrażeniach: Kiedy warunki nie opierają się na prostym porównaniu z wartością stałą, ale na wynikach bardziej skomplikowanych wyrażeń, if-else zapewnia większą elastyczność.

Przykład, gdzie if-else jest lepszy:


int wiek = 25;
decimal dochod = 50000m;
bool maKredyt = true; if (wiek >= 18 && wiek <= 65 && dochod > 30000m && !maKredyt)
{ Console.WriteLine("Osoba kwalifikuje się do nowego kredytu.");
}
else
{ Console.WriteLine("Osoba nie kwalifikuje się do nowego kredytu.");
}

Najczęstsze błędy i dobre praktyki jak unikać pułapek?

Nawet najbardziej użyteczne narzędzia programistyczne mogą stać się źródłem błędów, jeśli nie są używane poprawnie. Instrukcja switch, mimo swojej prostoty, ma kilka pułapek, których należy unikać, aby pisać niezawodny i łatwy w utrzymaniu kod. Oto przegląd najczęstszych błędów i najlepszych praktyk.

Pułapka braku `break` a świadome grupowanie przypadków

Najbardziej klasycznym błędem w tradycyjnym switch jest zapomnienie o instrukcji break; na końcu bloku case. Jak już wspominaliśmy, C# domyślnie zabrania "fall-through", co oznacza, że kompilator zgłosi błąd. Jeśli jednak świadomie chcemy, aby kilka przypadków wykonało ten sam kod, możemy je zgrupować. Robimy to, umieszczając etykiety case jedna po drugiej, a dopiero ostatnią z nich kończymy instrukcją break; lub inną instrukcją kończącą.


int kodStatusu = 401;
string komunikat; switch (kodStatusu)
{ case 200: // OK case 201: // Created case 204: // No Content komunikat = "Operacja zakończona sukcesem."; break; case 400: // Bad Request case 401: // Unauthorized case 403: // Forbidden komunikat = "Błąd autoryzacji lub żądania."; break; case 404: // Not Found komunikat = "Zasób nie został znaleziony."; break; default: komunikat = "Nieznany kod statusu."; break;
}
Console.WriteLine(komunikat); // Wyświetli: Błąd autoryzacji lub żądania.

Pamiętaj, że ten mechanizm grupowania działa tylko wtedy, gdy nie ma żadnego kodu między etykietami case.

Jak nie tworzyć potworów: Unikaj zbyt skomplikowanych i zagnieżdżonych `switch`

Instrukcja switch jest potężna, ale nadmierne jej użycie, zwłaszcza tworzenie bardzo długich, skomplikowanych lub zagnieżdżonych instrukcji switch, może znacząco obniżyć czytelność kodu i zwiększyć ryzyko błędów. Jeśli Twoja instrukcja switch zajmuje wiele ekranów lub zawiera inne instrukcje switch wewnątrz swoich bloków case, jest to silny sygnał, że kod wymaga refaktoryzacji.

Przeczytaj również: Jak otworzyć stronę HTML w przeglądarce i uniknąć typowych błędów

Kiedy `switch` jest sygnałem do refaktoryzacji? Wprowadzenie do polimorfizmu jako alternatywy

Bardzo często, rozbudowana instrukcja switch, która działa na typie obiektu (np. switch (obiekt.GetType().Name) lub switch (obiekt) z dopasowaniem po typie dla wielu klas pochodnych), jest tzw. "antywzorcem" (anti-pattern). W programowaniu obiektowym, gdy musimy podejmować decyzje w zależności od konkretnego typu obiektu, elegancką alternatywą jest polimorfizm. Zamiast używać switch do sprawdzania typu, możemy zaimplementować wirtualne metody w klasie bazowej i nadpisać je w klasach pochodnych. Wówczas wywołanie metody na obiekcie spowoduje automatyczne wykonanie odpowiedniej implementacji dla jego konkretnego typu, bez potrzeby jawnego sprawdzania typu w instrukcji switch. Jest to znacznie czystsze, bardziej skalowalne i zgodne z zasadami SOLID, zwłaszcza z zasadą otwarcia/zamknięcia (Open/Closed Principle).

Źródło:

[1]

https://csharp.net-tutorials.com/pl/111/struktury-kontrolne/instrukcja-switch/

[2]

https://stackoverflow.com/questions/18712749/c-sharp-switches-vs-vb-case-statements

FAQ - Najczęstsze pytania

Nie. W C# nie ma Select Case; funkcjonalnie odpowiada mu instrukcja switch, która porównuje wyrażenie z wartościami case.

Switch: switch (wyrażenie) { case wartość: // kod; break; default: // kod; break; }

Switch jest czytelny przy wielu stałych warunkach jednej zmiennej. If-else lepiej dla złożonych warunków, zakresów wartości i zależności między zmiennymi.

Pattern matching, od C# 7, pozwala dopasować typy i właściwości obiektów, a także warunki z when, rozszerzając możliwości switch.

Wyrażenia switch (switch expressions) zwracają wartość. Używają "=>" zamiast bloków; "_" działa jak default. Dzięki temu kod jest krótszy i bardziej funkcyjny.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0
rating-outline
rating-outline
rating-outline
rating-outline
rating-outline

Tagi

select case c
/
dopasowywanie wzorców w switch c#
/
wyrażenia switch c# 8.0 zwracanie wartości
/
switch vs if-else w c# porównanie
/
jak używać case i when w switch c#
/
odpowiednik select case visual basic w c#
Autor Cezary Michalak
Cezary Michalak
Jestem Cezary Michalak, doświadczony analityk branżowy z wieloletnim zaangażowaniem w obszarze technologii. Od ponad dziesięciu lat zajmuję się analizowaniem trendów rynkowych oraz innowacji w tej dynamicznej dziedzinie. Moja specjalizacja obejmuje technologie informacyjne oraz rozwój oprogramowania, co pozwala mi na głębokie zrozumienie złożonych zagadnień oraz ich wpływu na codzienne życie użytkowników. W mojej pracy stawiam na obiektywną analizę i fakt-checking, co sprawia, że moje teksty są rzetelne i oparte na aktualnych danych. Dążę do uproszczenia skomplikowanych informacji, aby były one przystępne dla szerokiego grona odbiorców. Moim celem jest dostarczanie czytelnikom dokładnych, aktualnych i obiektywnych informacji, które pomogą im lepiej zrozumieć świat technologii i jego wpływ na nasze życie.

Napisz komentarz