Выбрать главу

                   // Выбрано десятичное число

      break;

    default:

      Console.WriteLine("Your choice is something else");

                   // Выбрано что-то другое

      break;

  }

  Console.WriteLine();

}

В первом операторе switch используется стандартный образец с константами; он включен только ради полноты этого (тривиального) примера. Во втором операторе switch переменная типизируется как object и на основе пользовательского ввода может быть разобрана в тип данных int, string или decimal. В зависимости от типа переменной совпадения дают разные операторы case. Вдобавок к проверке типа данных в каждом операторе case выполняется присваивание переменной (кроме случая default). Модифицируйте код, чтобы задействовать значения таких переменных:

// Новый оператор switch, в котором применяется

// сопоставление с образцом с типами

switch (choice)

{

  case int i:

    Console.WriteLine("Your choice is an integer {0}.",i);

    break;

  case string s:

    Console.WriteLine("Your choice is a string. {0}", s);

    break;

  case decimal d:

    Console.WriteLine("Your choice is a decimal. {0}", d);

    break;

  default:

    Console.WriteLine("Your choice is something else");

    break;

}

Кроме оценки типа сопоставляющего выражения к операторам case могут быть добавлены конструкции when для оценки условий на переменной. В представленном ниже примере в дополнение к проверке типа производится проверка на совпадение преобразованного типа:

static void ExecutePatternMatchingSwitchWithWhen()

{

  Console.WriteLine("1 [C#], 2 [VB]");

  Console.Write("Please pick your language preference: ");

  object langChoice = Console.ReadLine();

  var choice = int.TryParse(langChoice.ToString(),

                            out int c) ? c : langChoice;

  switch (choice)

  {

    case int i when i == 2:

    case string s when s.Equals("VB", StringComparison.OrdinalIgnoreCase):

      Console.WriteLine("VB: OOP, multithreading, and more!");

                      // VB: ООП, многопоточность и многое другое!

      break;

    case int i when i == 1:

    case string s when s.Equals("C#", StringComparison.OrdinalIgnoreCase):

      Console.WriteLine("Good choice, C# is a fine language.");

                      // Хороший выбор. C# - замечательный язык.

      break;

    default:

      Console.WriteLine("Well...good luck with that!");

                      // Хорошо, удачи с этим!

      break;

  }

  Console.WriteLine();

}

Здесь к оператору switch добавляется новое измерение, поскольку порядок следования операторов case теперь важен. При использовании образца с константами каждый оператор case обязан быть уникальным. В случае применения образца с типами это больше не так. Например, следующий код будет давать совпадение для каждого целого числа в первом операторе case, а второй и третий оператор case никогда не выполнятся (на самом деле такой код даже не скомпилируется):

switch (choice)

{

  case int i:

    //do something

    break;

  case int i when i == 0:

    //do something

    break;

  case int i when i == -1:

    // do something

    break;

}

В первоначальном выпуске C# 7 возникало небольшое затруднение при сопоставлении с образцом, когда в нем использовались обобщенные типы. В версии C# 7.1 проблема была устранена. Обобщенные типы рассматриваются в главе 10.

На заметку! Все продемонстрированные ранее улучшения сопоставления с образцом в C# 9.0 также можно применять в операторах switch.

Использование выражений switch (нововведение в версии 8.0)

В версии C# 8 появились выражения switch, позволяющие присваивать значение переменной в лаконичном операторе. Рассмотрим версию C# 7 метода FromRainbowClassic(), который принимает имя цвета и возвращает для него шестнадцатеричное значение:

static string FromRainbowClassic(string colorBand)

{

  switch (colorBand)

  {

    case "Red":

      return "#FF0000";

    case "Orange":

      return "#FF7F00";

    case "Yellow":