Использование switch в C#: примеры и лучшие практики

Зачем использовать switch
Switch упорядочивает код, когда нужно выполнить разные действия в зависимости от значения одной переменной. Это более читабельно и менее подвержено ошибкам, чем длинная цепочка if-else, особенно если вариантов много и они сравниваются именно с одним значением.
Краткое определение: switch — конструкция управления потоком, которая сравнивает выражение с набором «case» и выполняет соответствующий блок кода.
Преимущества switch:
- Чёткая структура для множества альтернатив.
- Легче добавлять новые варианты (новые case).
- В большинстве случаев читабельнее, чем вложенные if.
Когда switch не подходит:
- Когда нужно проверять сложные логические выражения с несколькими переменными.
- Когда нужно гибко комбинировать условия (тогда if/&&/|| удобнее).
Что мы рассмотрим
- Простой пример консольного приложения на C# (строки и числа).
- Валидация ввода (int.TryParse вместо Parse).
- Добавление default-case и многострочные case.
- Современные возможности C#: switch expression, pattern matching, перечисления (enum).
- Альтернативы и критерии приёмки.
Пошаговый пример: консольное приложение со строками
- Создайте новый проект C# в Visual Studio.
- Выберите шаблон “Console Application”.
- Укажите имя проекта и папку.
- По умолчанию будет создан минимальный «Hello World». Замените вывод на запрос выбора опции пользователем:
// Display a list of options to the user
Console.WriteLine("Choose an option:");
Console.WriteLine("1. Fruit");
Console.WriteLine("2. Mains");
Console.WriteLine("3. Desserts");
Console.WriteLine();
// Request user input
Console.Write(">> ");
string meals = Console.ReadLine().ToLower();- Добавьте switch по строке meals:
switch (meals)
{
case "fruit":
Console.WriteLine("Fruits include apples, oranges, and bananas.");
break;
case "mains":
Console.WriteLine("Mains include steak, salmon, or risotto.");
break;
case "desserts":
Console.WriteLine("Desserts include chocolate cake, apple pie, or ice cream.");
break;
default:
Console.WriteLine("Please select one of the listed options.");
break;
}- Запустите программу.
- Введите “Fruit”, “Mains” или “Desserts” — вывод изменится в зависимости от выбора.
Использование числовых case и валидация ввода
Иногда удобнее позволять пользователю вводить число (1, 2, 3). В этом случае важно безопасно конвертировать строку в число. Рекомендуется использовать int.TryParse, чтобы избежать исключений.
Пример безопасной валидации:
Console.Write(">> ");
string input = Console.ReadLine();
if (!int.TryParse(input, out int result))
{
Console.WriteLine($"'{input}' is an invalid format. Please enter a number.");
return; // или Environment.Exit(1);
}
switch (result)
{
case 1:
Console.WriteLine("You selected option 1 (Fruit), which includes apples, oranges, and bananas.");
break;
case 2:
Console.WriteLine("You selected option 2 (Mains), which includes steak, salmon, or risotto.");
break;
case 3:
Console.WriteLine("You selected option 3 (Desserts), which includes chocolate cake, apple pie or ice cream.");
break;
default:
Console.WriteLine("The number you entered is not part of the available options.");
break;
}Советы по обработке данных пользователя
- Всегда валидируйте ввод (TryParse, регулярные выражения, длину строки).
- Приводите строки к одному регистру (ToLower/ToUpper) перед сравнением.
- Для локализации сообщений используйте ресурсы (resx).
- В UI‑интерактивных приложениях лучше использовать числовые коды и отображать текст пользователю отдельно – это уменьшит вероятность опечаток.
Когда нужен default
Если значение не совпадает ни с одним case, выполняется default (если он есть). Без default код просто продолжит выполняться после switch — но часто логично обработать неожиданные значения и вывести понятное сообщение или лог.
Современные подходы в C# (switch expression и pattern matching)
Начиная с C# 8 и выше появились более компактные выражения switch и сопоставление с образцом (pattern matching). Они облегчают код там, где switch используется для выбора значения, а не только для операций ввода/вывода.
Пример switch expression:
string message = meals.ToLower() switch
{
"fruit" => "Fruits include apples, oranges, and bananas.",
"mains" => "Mains include steak, salmon, or risotto.",
"desserts" => "Desserts include chocolate cake, apple pie, or ice cream.",
_ => "Please select one of the listed options."
};
Console.WriteLine(message);Pattern matching: можно сопоставлять не только значения, но и типы, свойства и диапазоны.
object value = GetSomeValue();
switch (value)
{
case int i when i > 0:
Console.WriteLine("Positive integer");
break;
case string s:
Console.WriteLine($"String of length {s.Length}");
break;
case null:
Console.WriteLine("Null value");
break;
default:
Console.WriteLine("Other type");
break;
}Работа с enum вместо «магических» чисел/строк
Если набор вариантов фиксирован и используется по всему коду, лучше определить enum. Это делает код самодокументируемым и уменьшает риск опечаток.
enum MealType { Fruit = 1, Mains = 2, Desserts = 3 }
if (int.TryParse(input, out int val) && Enum.IsDefined(typeof(MealType), val))
{
var meal = (MealType)val;
switch (meal)
{
case MealType.Fruit:
Console.WriteLine("...");
break;
// ...
}
}Альтернативы switch и когда их выбирать
- if/else: когда условия сложные (несколько переменных, диапазоны и комбинированные логические выражения).
- Dictionary
: когда хотите полностью избавиться от switch и динамически добавлять обработчики. - Полиморфизм (виртуальные методы/интерфейсы): когда разные типы данных имеют свои реализации поведения.
Пример словаря:
var handlers = new Dictionary
{
["fruit"] = () => Console.WriteLine("...") ,
["mains"] = () => Console.WriteLine("...") ,
};
if (handlers.TryGetValue(meals, out var action)) action();
else Console.WriteLine("Unknown option"); Частые ошибки и когда switch «ломается”
- Использование Parse вместо TryParse — приложение может упасть из‑за FormatException.
- Сравнение строк без нормализации регистра/культуры — локализованные строки могут не совпасть.
- Отсутствие default для непредвиденных значений — труднее отлаживать.
- Неучёт null при работе со ссылочными типами (в C# 8+ есть nullable reference types).
Чек‑лист перед слиянием в мастер (роль: разработчик)
- Ввод валидирован (TryParse, проверки диапазона).
- Есть default или обработка невалидных значений.
- Текстовые сравнения нормализованы (ToLowerInvariant/ToUpperInvariant или StringComparer).
- Не используются «магические» литералы — рассмотрите enum.
- Юнит‑тесты покрывают все case и default.
Критерии приёмки
- Приложение корректно обрабатывает все заявленные варианты ввода.
- Для невалидного ввода выводится информативное сообщение и приложение не падает.
- Локализация строк вынесена в ресурсы при необходимости.
- Есть тесты для позитивных и негативных сценариев.
Тест‑кейсы и приёмочные сценарии
- Ввод “1” — ожидается список фруктов.
- Ввод “Fruit” (регистронезависимо) — ожидается тот же вывод.
- Ввод “4” — ожидается сообщение из default.
- Ввод “abc” — ожидается сообщение об ошибке формата и отсутствие исключения.
- Null/пустая строка — корректная обработка (например, сообщение о выборе).
Мини‑методология внедрения switch в проект
- Определите набор возможных значений (строки/числа/enum).
- Решите: нужен ли enum или достаточно строк/чисел.
- Добавьте безопасную валидацию ввода.
- Реализуйте switch/switch expression с default.
- Покройте тестами и добавьте документацию (комментарии/README).
Быстрый шпаргалка (cheat sheet)
- Используйте int.TryParse вместо Int32.Parse.
- Для строк — ToLowerInvariant() и StringComparer.OrdinalIgnoreCase.
- Для расширяемости — Dictionary
или enum. - Для простого выбора значения — switch expression компактнее.
Краткое резюме
Switch — хорошая практика для выбора по одному значению. В современных версиях C# есть дополнительные возможности, такие как switch expression и pattern matching, которые делают код ещё компактнее и безопаснее. Всегда валидируйте ввод, покрывайте кейсы тестами и рассматривайте enum для фиксированных наборов значений.
Важно: выбирайте инструмент под задачу — если условия сложнее, чем простое сравнение с набором значений, предпочтительнее if, полиморфизм или структура данных с обработчиками.
Похожие материалы
Безопасная температура GPU и как её проверить
Исправление ERROR_FAIL_SHUTDOWN в Windows
Резервное копирование Minecraft: миры, моды и настройки
Запуск нескольких дистрибутивов Linux с помощью chroot
Установка Arch Linux на Raspberry Pi