Avatar ·

Несколько вариантов в одном case оператора switch в C# — как правильно?

Всем привет. Я только начал изучать C# и столкнулся с проблемой при использовании оператора switch. Мне нужно, чтобы один и тот же блок кода выполнялся для нескольких разных значений переменной. Например, я пишу простую программу, которая определяет день недели по числу (1 — понедельник, 2 — вторник и т.д.). Но мне нужно, чтобы для выходных (суббота и воскресенье) выводилось одно сообщение, а для будних дней — другое. Я пробовал написать так: ```csharp int day = 6; switch (day) { case 1: case 2: case 3: case 4: case 5: Console.WriteLine("Будний день"); break; case 6: case 7: Console.WriteLine("Выходной"); break; default: Console.WriteLine("Неверный день"); break; } ``` Это работает, но мне сказали, что в новых версиях C# есть более элегантный способ. Я слышал про pattern matching, но не понимаю, как его применить для нескольких значений. Подскажите, как правильно писать такой код в современном C#? Можно ли объединить несколько case в одну строку? Или есть другие подходы, которые делают код чище? Заранее спасибо за помощь! <<>>

Объединение нескольких case с помощью pattern matching в C# 8.0+

Вы абсолютно правы — в современных версиях C# (начиная с 8.0) появился более элегантный способ обработки нескольких значений в одном блоке switch. Это называется pattern matching (сопоставление с образцом). Давайте разберём несколько подходов от простого к сложному.

1. Классический способ (работает во всех версиях)

Ваш текущий код абсолютно корректен. Это стандартный подход, который используется десятилетиями. Он надёжен и понятен:

int day = 6;
switch (day)
{
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        Console.WriteLine("Будний день");
        break;
    case 6:
    case 7:
        Console.WriteLine("Выходной");
        break;
    default:
        Console.WriteLine("Неверный день");
        break;
}

Минус — многословность. Но если вам важна совместимость со старыми версиями C# (до 7.0), это лучший выбор.

2. Pattern matching с оператором "or" (C# 9.0+)

Начиная с C# 9.0, вы можете использовать логический оператор or прямо в case:

int day = 6;
switch (day)
{
    case 1 or 2 or 3 or 4 or 5:
        Console.WriteLine("Будний день");
        break;
    case 6 or 7:
        Console.WriteLine("Выходной");
        break;
    default:
        Console.WriteLine("Неверный день");
        break;
}

Это гораздо компактнее и читаемее. Обратите внимание: or — это ключевое слово, а не логический оператор ||. Его можно использовать только в контексте pattern matching.

3. Switch-выражение (C# 8.0+) — самый лаконичный вариант

Если вам нужно просто вернуть значение, используйте switch-выражение. Это современный функциональный подход:

int day = 6;
string result = day switch
{
    1 or 2 or 3 or 4 or 5 => "Будний день",
    6 or 7 => "Выходной",
    _ => "Неверный день"
};
Console.WriteLine(result);

Здесь _ — это аналог default. Switch-выражения обязаны быть исчерпывающими (покрывать все возможные значения), иначе компилятор выдаст предупреждение.

4. Pattern matching с диапазонами (для последовательных значений)

Если ваши значения идут подряд, можно использовать диапазоны:

int day = 6;
string result = day switch
{
    >= 1 and <= 5 => "Будний день",
    6 or 7 => "Выходной",
    _ => "Неверный день"
};

Обратите внимание на and — это тоже ключевое слово для pattern matching. Такой подход особенно полезен, когда значений много (например, от 1 до 100).

5. Когда использовать какой подход?

  • Классический switch — если код должен работать на старых версиях .NET Framework (до 4.8).
  • Switch с "or" — если вам нужен привычный синтаксис switch-case, но более компактный.
  • Switch-выражение — для современных проектов на .NET Core/5+, особенно если вы используете функциональный стиль.
  • Диапазоны — когда значения образуют непрерывный интервал.

Лично я рекомендую использовать switch-выражения для новых проектов — они делают код чище и снижают вероятность ошибок (например, забытого break).

Важно помнить: если вы используете or или switch-выражения, убедитесь, что ваша версия C# поддерживает эти функции. Для .NET 6+ и Visual Studio 2022 все описанное работает без дополнительных настроек.

<<>>

Альтернативный подход: использование словаря (Dictionary) для маппинга

Если ваша логика становится сложнее (например, разные дни требуют разных действий, а не просто возврата строки), можно использовать словарь с делегатами. Это особенно полезно, когда количество вариантов велико или они динамически загружаются.

var dayActions = new Dictionary<int, Action>
{
    { 1, () => Console.WriteLine("Понедельник — тяжёлый день") },
    { 2, () => Console.WriteLine("Вторник — рабочий") },
    { 3, () => Console.WriteLine("Среда — маленькая пятница") },
    { 4, () => Console.WriteLine("Четверг — почти пятница") },
    { 5, () => Console.WriteLine("Пятница — развратница") },
    { 6, () => Console.WriteLine("Суббота — выходной!") },
    { 7, () => Console.WriteLine("Воскресенье — отдых") }
};

int day = 6;
if (dayActions.TryGetValue(day, out var action))
    action();
else
    Console.WriteLine("Неверный день");

Преимущества этого подхода:

  • Легко добавлять/удалять варианты без изменения структуры switch.
  • Можно хранить маппинг в конфигурации или базе данных.
  • Удобно для тестирования — словарь можно подменять.

Недостаток — код становится менее очевидным для новичков. Используйте этот подход, когда switch-case начинает разрастаться и нарушать принцип единственной ответственности (Single Responsibility).