Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
Console.WriteLine("It’s the weekend!");
break;
Помещение любого кода между операторами case приведет к тому, что компилятор сообщит об ошибке. До тех пор, пока операторы case следуют друг за другом, как показано выше, их можно комбинировать для разделения общего кода.
В дополнение к операторам return и break, показанным в предшествующих примерах кода, оператор switch также поддерживает применение goto для выхода из условия case и выполнения другого оператора case. Несмотря на наличие поддержки, данный прием почти повсеместно считается антипаттерном и в общем случае не рекомендуется. Ниже приведен пример использования оператора goto в блоке switch:
static void SwitchWithGoto()
{
var foo = 5;
switch (foo)
{
case 1:
// Делать что-то
goto case 2;
case 2:
// Делать что-то другое
break;
case 3:
// Еще одно действие
goto default;
default:
// Стандартное действие
break;
}
}
Выполнение сопоставления с образцом в операторах switch (нововведение в версии 7.0, обновление в версии 9.0)
До выхода версии C# 7 сопоставляющие выражения в операторах switch ограничивались сравнением переменной с константными значениями, что иногда называют образцом с константами. В C# 7 операторы switch способны также задействовать образец с типами, при котором операторы case могут оценивать тип проверяемой переменной, и выражения case больше не ограничиваются константными значениями. Правило относительно того, что каждый оператор case должен завершаться с помощью return или break, по-прежнему остается в силе; тем не менее, операторы goto не поддерживают применение образца с типами.
На заметку! Если вы новичок в объектно-ориентированном программировании, тогда материал этого раздела может слегка сбивать с толку. Все прояснится в главе 6, когда мы вернемся к новым средствам сопоставления с образцом C# 7 в контексте базовых и производных классов. Пока вполне достаточно понимать, что появился мощный новый способ написания операторов switch.
Добавьте еще один метод по имени ExecutePatternMatchingSwitch() со следующим кодом:
static void ExecutePatternMatchingSwitch()
{
Console.WriteLine("1 [Integer (5)], 2 [String ("Hi")], 3 [Decimal (2.5)]");
Console.Write("Please choose an option: ");
string userChoice = Console.ReadLine();
object choice;
// Стандартный оператор switch, в котором применяется
// сопоставление с образцом с константами
switch (userChoice)
{
case "1":
choice = 5;
break;
case "2":
choice = "Hi";
break;
case "3":
choice = 2.5;
break;
default:
choice = 5;
break;
}
// Новый оператор switch, в котором применяется
// сопоставление с образцом с типами
switch (choice)
{
case int i:
Console.WriteLine("Your choice is an integer.");
// Выбрано целое число
break;
case string s:
Console.WriteLine("Your choice is a string.");
// Выбрана строка
break;
case decimal d:
Console.WriteLine("Your choice is a decimal.");
// Выбрано десятичное число
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 обязан быть уникальным. В случае применения образца с типами это больше не так. Например, следующий