Как работает switch / switch case в C#?
Пишу обработчик команд и наставник посоветовал заменить кучу if-else на switch. Я нашёл два разных синтаксиса: со старыми case ... break и какой-то новый со стрелочками =>. Чем они отличаются и когда что брать? И правда ли, что в C# нельзя «провалиться» из одного case в другой, как в C?
2 ответа
Давай по порядку, тут два разных инструмента с похожим именем.
1. Классический switch-statement. Сравнивает значение с каждым case и выполняет совпавшую ветку. default — на случай, когда ничего не подошло.
string DescribeDay(int day)
{
switch (day)
{
case 6:
case 7:
return "Выходной";
case 1:
return "Понедельник, держись";
default:
return "Будний день";
}
}
Обрати внимание: каждая ветка обязана закончиться break, return или throw. В C, если забыть break, выполнение «проваливается» в следующий case — это источник багов. В C# fall-through запрещён, компилятор просто не даст собрать код без выхода из ветки. Единственное исключение — несколько case подряд без тела (как 6 и 7 выше): это группировка, а не fall-through.
2. switch expression (C# 8). Это уже выражение, которое возвращает значение, а не управляет потоком. Короче и без break:
string DescribeDay(int day) => day switch
{
6 or 7 => "Выходной",
1 => "Понедельник, держись",
_ => "Будний день" // _ это аналог default
};
Здесь работает сопоставление с шаблоном: можно писать > 100 => ..., проверять тип Circle c => ... и т.д.
Когда что: нужно выполнить действия (логирование, вызовы) — бери statement; нужно по входу получить значение — бери expression, он чище. Почему так: expression заставляет покрыть все случаи (иначе предупреждение/исключение), и это ловит ошибки на этапе компиляции.
Добавлю про производительность и читаемость. Когда веток много (десятки), компилятор C# умеет превращать switch по константам в эффективную таблицу переходов (jump table), тогда как длинная цепочка if-else проверяется по очереди. Так что switch — это не только красиво, но иногда и быстрее.
И маленький совет: в switch expression не забывай ветку _. Если входное значение не попадёт ни в один шаблон, C# кинет SwitchExpressionException в рантайме — а это уже падение, а не безобидный пропуск.