CodeGym /Kursy /C# SELF /switch-wyrażenia i n...

switch-wyrażenia i nowe wzorce

C# SELF
Poziom 10, Lekcja 5
Dostępny

1. Wprowadzenie

Już umiesz pisać taki kod:

switch (color)
{
    case "red":
        Console.WriteLine("Stop!");
        break;
    case "yellow":
        Console.WriteLine("Czekaj...");
        break;
    case "green":
        Console.WriteLine("Możesz iść!");
        break;
    default:
        Console.WriteLine("A co to za kolor?");
        break;
}

Ale co jeśli chcemy przypisać zmiennej różną wartość w zależności od parametru wejściowego, na przykład zwrócić string oparty na liczbie z funkcji? Przed pojawieniem się switch-wyrażeń trzeba było pisać takie konstrukcje:

string znaczenie;
switch (number)
{
    case 42:
        znaczenie = "Odpowiedź na główne pytanie życia, wszechświata i w ogóle wszystkiego";
        break;
    case 7:
        znaczenie = "Szczęśliwa liczba";
        break;
    default:
        znaczenie = "Zwykła liczba";
        break;
}

Trochę to mało eleganckie jak na język XXI wieku, nie? Chciałoby się od razu zwrócić wartość, jak to bywa w językach funkcyjnych.

I tu właśnie pojawiają się switch-wyrażenia — jedna z najfajniejszych (i najświeższych) możliwości C#, od wersji 8.0.

2. switch-wyrażenia: składnia, którą chce się przytulić

Porównajmy: operator i wyrażenie
Klasyczny switch to statement ("operator"), a switch-wyrażenie to expression, czyli oblicza wartość i można ją od razu przypisać do zmiennej albo zwrócić z metody.

Struktura switch-wyrażenia:


var result = value switch
{
    pattern1 => expression1,
    pattern2 => expression2,
    _       => defaultExpression // "podkreślenie" - to "inaczej"
};
Składnia switch-wyrażenia

Na przykład:

int number = 42;
string znaczenie = number switch
{
    42 => "Odpowiedź na główne pytanie życia, wszechświata i w ogóle wszystkiego",
    7  => "Szczęśliwa liczba",
    _  => "Zwykła liczba"
};
Console.WriteLine(znaczenie); // => Odpowiedź na główne pytanie życia, wszechświata i w ogóle wszystkiego

Wszystko zwięźle, czytelnie, żadnych tasiemców kodu, ani jednego break;.

Zwróć uwagę: podkreślenie _ — to "złap wszystkie pozostałe przypadki", odpowiednik default.

3. switch-wyrażenia i wzorce: jak to się łączy

I tu zaczyna się prawdziwa zabawa. W switch-wyrażeniach możesz używać nie tylko zwykłych wartości, ale też wzorców: sprawdzania zakresu, typu, właściwości obiektów, dekompozycji (rozbijania obiektu na części), a nawet combinatorial patterns (and, or, not).

Przykłady wzorców w switch-wyrażeniu

Wzorce stałe
To właśnie to, co robiliśmy wyżej: porównanie z 42, 7 itd.

Zakresy i porównania

int wiek = 17;
string kategoria = wiek switch
{
    < 18 => "Niepełnoletni",
    >= 18 and <= 65 => "Dorosły",
    > 65 => "Osoba starsza",
    _ => "Nieznana kategoria wiekowa"
};
Console.WriteLine(kategoria);

Przy okazji, zwróć uwagę — można używać kilku warunków naraz! C# robi się coraz bardziej wyrazisty.

Wzorce typów (Type Patterns)

Załóżmy, że mamy obiekt, który może być różnego typu (np. object value;). Możemy obsłużyć różne typy tak:

object value = 3.14;
string opis = value switch
{
    int i => $"Liczba całkowita: {i}",
    double d => $"Liczba zmiennoprzecinkowa: {d:F2}",
    string s => $"To jest string: '{s}'",
    null => "null!",
    _ => "Coś innego"
};
Console.WriteLine(opis); // => Liczba zmiennoprzecinkowa: 3.14

Wzorce powiązane (Property Patterns i Positional Patterns)

Od C# 8 i dalej możemy sprawdzać wartości właściwości bezpośrednio w switch-wyrażeniu.

Przykład z obiektem

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

User user = new User { Name = "Anna", Age = 17 };
string powitanie = user switch
{
    { Age: < 18 } => $"Cześć, {user.Name}! Jesteś nastolatkiem.",
    { Age: >= 18 and <= 65 } => $"Hej, {user.Name}! Dorosłe życie jest super.",
    { Age: > 65 } => $"Witamy, {user.Name}! Zawsze miło Cię widzieć.",
    _ => "Nieznany wiek"
};
Console.WriteLine(powitanie);

Tutaj w klamrach { Age: < 18 } — to property pattern, czyli sprawdzamy nie cały obiekt, a tylko jego właściwość.

4. Nowe wzorce C# 11-14

C# dąży do zwięzłości i elastyczności. Ostatnio pojawiły się w nim combinatorial patterns: and, or, not, a także ulepszone positional patterns. Zobaczmy je w akcji.

Wzorce logiczne: and, or, not

Możesz budować złożone warunki jak w matematycznej logice!

int temperatura = 25;
string wynik = temperatura switch
{
    < 0 => "Mróz!",
    >= 0 and < 20 => "Chłodno",
    >= 20 and < 30 => "Komfortowo",
    >= 30 or <= -30 => "Ekstremalnie!",
    _ => "Dziwna temperatura"
};

Jeśli chcesz wykluczyć przypadki, proszę bardzo:

int wynikTestu = 80;
string ocena = wynikTestu switch
{
    >= 90 => "Świetnie",
    >= 60 and not >= 90 => "Dobrze",
    _ => "Słabo"
};

Dekonstrukcja (Positional Patterns)

Jeśli masz strukturę lub record, który wspiera dekonstrukcję, C# pozwala rozbić obiekt bezpośrednio w switch-wyrażeniu:

public record Point(int X, int Y);

Point p = new Point(10, 20);
string opis = p switch
{
    (0, 0) => "Początek układu współrzędnych",
    (var x, 0) => $"Na osi X, X={x}",
    (0, var y) => $"Na osi Y, Y={y}",
    (var x, var y) when x == y => $"Na przekątnej: {x}",
    _ => $"W punkcie ({p.X}, {p.Y})"
};
Console.WriteLine(opis); // => W punkcie (10, 20)

5. Kiedy i po co używać switch-wyrażeń

W nowoczesnym C# switch-wyrażenia to nie tylko modny "ficzer", ale realny sposób na uniknięcie klepania kodu, zrobienie go bardziej kompaktowym, łatwiejszym do testowania i utrzymania. To szczególnie ważne przy pisaniu parserów, handlerów komend, logiki biznesowej, konfiguracji reguł — wszędzie tam, gdzie trzeba rozgałęziać wykonanie po złożonych kryteriach, nie tylko po wartościach, ale też po typach, zakresach, właściwościach, kombinacjach.

Na rozmowie rekrutacyjnej

  • Jak obsłużyłbyś różne warianty odpowiedzi od użytkownika?
  • Jak zrobić, żeby zwrócić różną wartość funkcji zależną i od typu, i od wartości?
  • Jak łatwo dodawać nowe reguły bez tony if-else?

Pokaż switch-wyrażenie z wzorcami! To od razu pokaże, że znasz nowe możliwości języka i masz dobry styl kodowania.

Tabela: porównanie switch-operatora i switch-wyrażenia

Charakterystyka switch statement switch expression
Typ operator (statement) wyrażenie (expression)
Użycie break obowiązkowe niepotrzebny
Może zwracać wartość tylko przez zmienną tak, od razu zwraca wartość
Może używać wzorców częściowo w pełni (type, property, itd.)
Pułapka można zapomnieć break wszystkie ścieżki muszą zwracać wartość

6. Typowe błędy i drobne złośliwości

  • Początkujący programiści często mylą różnicę między switch-operatorem ("statement") a switch-wyrażeniem ("expression"). Na przykład zapominają, że w switch-wyrażeniu nie potrzeba break;, a wszystkie gałęzie muszą koniecznie zwracać wartość.
  • Jeśli zapomnisz gałęzi _, kompilator podpowie: "a co jeśli nic nie pasuje?".
  • W switch-wyrażeniu nie można używać goto (i całe szczęście!).
  • Jeśli powtórzysz warunek (np. dwa takie same wzorce), kompilator też tego nie przepuści.
  • Zwracaj uwagę na typ wartości zwracanej z switch-wyrażenia: musi być zgodny z typem zmiennej, do której to wszystko przypisujesz.
2
Zadanie
C# SELF, poziom 10, lekcja 5
Niedostępne
Proste wyrażenie switch z patternami
Proste wyrażenie switch z patternami
2
Zadanie
C# SELF, poziom 10, lekcja 5
Niedostępne
Walidacja hasła według długości i znaków
Walidacja hasła według długości i znaków
1
Ankieta/quiz
Stałe i słowo kluczowe var, poziom 10, lekcja 5
Niedostępny
Stałe i słowo kluczowe var
Stałe, struktury, enum i switch
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION