Урок 3.6 — Оператор switch
Множественный выбор без цепочек if. От классического switch до pattern matching.
Когда нужно проверить переменную на множество возможных значений, цепочка if-else if становится громоздкой. Представь: «если день 1 — понедельник, если 2 — вторник... если 7 — воскресенье». Семь if-else — это много кода и плохая читаемость. C# предлагает элегантное решение — оператор switch.
Синтаксис switch
Switch проверяет выражение и сравнивает его с несколькими возможными значениями (case). Вот базовая структура:
Общая схема:
switch (выражение)
{
case значение1:
// код для значения1
break;
case значение2:
// код для значения2
break;
default:
// код, если ни один case не подошёл
break;
}
int dayNumber = 3;
string dayName;
switch (dayNumber)
{
case 1:
dayName = "Понедельник";
break;
case 2:
dayName = "Вторник";
break;
case 3:
dayName = "Среда";
break;
case 4:
dayName = "Четверг";
break;
case 5:
dayName = "Пятница";
break;
case 6:
dayName = "Суббота";
break;
case 7:
dayName = "Воскресенье";
break;
default:
dayName = "Неизвестный день";
break;
}
Console.WriteLine(dayName); // Среда
Отличие switch от if-else if
Когда использовать switch, а когда if-else if? Вот ключевые различия:
💡 Простое правило: если ты проверяешь одну переменную на равенство с константами (1, 2, 3 или "красный", "зелёный", "синий") — используй switch. Если условие сложнее (диапазоны, комбинации) — if-else if.
Case-блоки и обязательный break
В C# каждый case-блок обязательно должен заканчиваться одним из:
break;— выход из switchreturn;— выход из методаthrow;— выброс исключенияgoto case X;— переход к другому case (существует, но использовать редко)
// ❌ Так нельзя — ошибка компиляции!
// switch (x)
// {
// case 1:
// Console.WriteLine("Один");
// // забыли break!
// case 2:
// Console.WriteLine("Два");
// break;
// }
// ✅ Так правильно:
switch (x)
{
case 1:
Console.WriteLine("Один");
break;
case 2:
Console.WriteLine("Два");
break;
}
Default-ветка
Блок default — аналог else в if-else. Он выполняется, если ни один из case не подошёл. default необязателен, но его рекомендуется добавлять всегда — на случай непредвиденных значений.
Console.Write("Введите оценку (1-5): ");
int grade = Convert.ToInt32(Console.ReadLine());
switch (grade)
{
case 5:
Console.WriteLine("Отлично!");
break;
case 4:
Console.WriteLine("Хорошо");
break;
case 3:
Console.WriteLine("Удовлетворительно");
break;
case 2:
case 1:
Console.WriteLine("Неудовлетворительно");
break;
default:
Console.WriteLine("Некорректная оценка!");
break;
}
Switch с множественными значениями (case 1: case 2:)
Если несколько значений должны приводить к одному результату, можно перечислить их подряд (в C# это разрешено, если объединяемые case пустые, без кода):
string category = "fruit";
switch (category)
{
case "apple":
case "banana":
case "orange":
Console.WriteLine("Это фрукт");
break;
case "carrot":
case "broccoli":
case "potato":
Console.WriteLine("Это овощ");
break;
default:
Console.WriteLine("Неизвестная категория");
break;
}
Pattern matching в switch (C# 7+)
Начиная с C# 7, switch стал гораздо мощнее. Теперь можно проверять не только равенство, но и тип переменной, а также добавлять дополнительные условия (when):
object value = 42;
switch (value)
{
case int i when i > 0:
Console.WriteLine($"Положительное целое: {i}");
break;
case int i when i < 0:
Console.WriteLine($"Отрицательное целое: {i}");
break;
case int i:
Console.WriteLine($"Целое число: {i}");
break;
case string s:
Console.WriteLine($"Строка: {s}");
break;
case double d:
Console.WriteLine($"Дробное: {d}");
break;
case null:
Console.WriteLine("null");
break;
default:
Console.WriteLine("Неизвестный тип");
break;
}
Ключевое слово when добавляет дополнительное условие к case. Это как if внутри case. Порядок case важен: более конкретные условия должны быть выше.
💡 Pattern matching позволяет использовать switch не только с примитивными типами, но и с объектами, проверяя их тип и свойства. Это особенно полезно при работе с иерархиями классов (полиморфизм).
Switch-выражение (C# 8+)
Начиная с C# 8, появился switch как выражение. Он возвращает значение и записывается в компактной форме. Это как тернарный оператор, но для множества вариантов:
// Старый switch (оператор):
string GetDayOld(int day)
{
switch (day)
{
case 1: return "Пн";
case 2: return "Вт";
case 3: return "Ср";
case 4: return "Чт";
case 5: return "Пт";
case 6: return "Сб";
case 7: return "Вс";
default: return "?";
}
}
// Новый switch (выражение), C# 8+:
string GetDayNew(int day) => day switch
{
1 => "Пн",
2 => "Вт",
3 => "Ср",
4 => "Чт",
5 => "Пт",
6 => "Сб",
7 => "Вс",
_ => "?"
};
Console.WriteLine(GetDayNew(3)); // Ср
Ключевые отличия switch-выражения:
- Используется стрелка
=>вместо двоеточия: - Нет
break— каждый вариант сам возвращает значение - Нет
case— пишется значение сразу _— это discard (аналог default)- Это выражение, его можно присвоить переменной
// Switch-выражение с дополнительными условиями
string GetCategory(int score) => score switch
{
>= 90 => "Отлично",
>= 75 => "Хорошо",
>= 50 => "Удовлетворительно",
_ => "Неудовлетворительно"
};
Console.WriteLine(GetCategory(85)); // Хорошо
// Можно комбинировать с паттернами типов:
object obj = 3.14;
string description = obj switch
{
int i => $"Целое: {i}",
double d => $"Дробное: {d}",
string s => $"Строка: {s}",
_ => "Неизвестный тип"
};
Console.WriteLine(description); // Дробное: 3.14
Сводный пример — калькулятор
Напишем простой калькулятор с switch:
using System;
class Program
{
static void Main()
{
Console.Write("Введите первое число: ");
double a = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите оператор (+, -, *, /): ");
string op = Console.ReadLine().Trim();
Console.Write("Введите второе число: ");
double b = Convert.ToDouble(Console.ReadLine());
double result = op switch
{
"+" => a + b,
"-" => a - b,
"*" => a * b,
"/" => b != 0 ? a / b : double.NaN,
_ => double.NaN
};
if (double.IsNaN(result))
Console.WriteLine("Ошибка: некорректный оператор или деление на ноль");
else
Console.WriteLine($"{a} {op} {b} = {result}");
}
}
Мини-тест
Проверь свои знания о switch.
Вопрос 1
int x = 2;
switch (x)
{
case 1:
Console.Write("A ");
case 2:
Console.Write("B ");
case 3:
Console.Write("C ");
break;
}
Варианты: A) Ошибка компиляции B) B C C) A B C
Вопрос 2
string result = 5 switch
{
1 => "A",
2 => "B",
_ => "C"
};
Console.WriteLine(result);
Варианты: A) A B) B C) C
Вопрос 3
object obj = "hello";
string desc = obj switch
{
int => "число",
string => "строка",
_ => "другое"
};
Console.WriteLine(desc);
Варианты: A) число B) строка C) другое
Вопрос 4
int code = 404;
string message = code switch
{
200 => "OK",
404 => "Not Found",
500 => "Server Error"
};
Console.WriteLine(message);
Варианты: A) OK B) Not Found C) Ошибка компиляции (нет _)
Задача
Задание: Конвертер валют
Напиши программу-конвертер валют. Пользователь вводит сумму в рублях и выбирает целевую валюту. Используй switch-выражение для выбора курса.
Валюты и курсы (условные):
- USD — 0.011 (доллар США)
- EUR — 0.010 (евро)
- CNY — 0.079 (юань)
- KZT — 5.20 (тенге)
- TRY — 0.32 (лира)
Дополнительно:
- Если валюта не поддерживается — выведи сообщение об ошибке
- Сумму на выходе округли до 2 знаков после запятой
Пример работы:
Сумма в рублях: 5000
Валюта (USD, EUR, CNY, KZT, TRY): USD
5000 RUB = 55.00 USD
Что важно запомнить
case 1: case 2:_ (discard).Тест: 3.6: Оператор switch
5 вопросов