Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Tip
Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Начните с обзора сопоставления шаблонов , если вы не знакомы с шаблонами. Полные языковые правила см. в реляционных шаблонах и логических шаблонах в справочнике по языку.
Реляционные и логические шаблоны описывают диапазоны, альтернативы и исключения. Следующий метод объединяет их для классификации температуры:
static string ClassifyTemperature(int temperature) =>
temperature switch
{
< 0 => "Below freezing",
>= 18 and <= 24 => "Comfortable",
(>= 0 and < 10) or > 30 => "Far outside the comfortable range",
_ => "Cool or warm"
};
Выражение temperature — это входные данные шаблона. C# вычисляет это выражение один раз, и каждая ветвь switch проверяет полученное значение. Оружие демонстрирует следующие тесты:
-
< 0проверяет одно граничное значение. -
>= 18 and <= 24проверяет диапазон. -
(>= 0 and < 10) or > 30проверяет два альтернативных диапазона.
В этой статье показаны как шаблоны, так и императивные условия, чтобы вы могли узнать каждую форму и сравнить, как они выражают одни и те же решения. Одно условие может выглядеть аналогично в любой форме. Шаблоны могут упростить чтение ряда связанных ветвей, сохраняя выбор рядом с их результатами. Выберите форму, которая упрощает понимание кода.
Сравнение значений с реляционными шаблонами
Реляционный шаблон сравнивает входные данные шаблона с константой времени компиляции с помощью <, ><=или >=.
Константой во время компиляции является значение, которое компилятор может оценить при компиляции программы. Числовые и символьные литералы, а const также переменные совместимых числовых или символьных типов являются репрезентативными примерами. Обычные переменные, свойства, вызовы методов и static readonly поля не являются константами во время компиляции. В первом примере оба >= 18 и <= 24 проверяют одно и то же вычисленное значение temperature.
Тот же реляционный символ может отображаться в обычном выражении или в шаблоне. В следующем примере используются обе формы с температурой:
static void ShowExpressionAndPattern(int temperature, int threshold)
{
bool belowThreshold = temperature < threshold;
bool belowFreezing = temperature is < 0;
string description = temperature switch
{
< 0 => "Freezing",
0 => "Freezing point",
> 0 => "Above freezing"
};
Console.WriteLine(
$"Below threshold: {belowThreshold}; " +
$"below freezing: {belowFreezing}; {description}");
}
temperature < threshold — реляционное выражение. Вычисляет оба операнда и возвращает bool. Любой из операндов может быть неконстантным выражением.
В temperature is < 0temperature является входным выражением шаблона. C# вычисляет его, а реляционный шаблон < 0 проверяет полученное значение. В ветви switch < 0 => "Freezing" выражение перед switch задаёт входное значение, поэтому образец содержит только < 0.
Выражение может сравниться temperature с переменной threshold. Операнд реляционного шаблона должен быть константой времени компиляции, поэтому используйте реляционное выражение, если значение сравнения является переменной. Если значение сравнения является константой, любая форма может работать.
Если правый операнд — константа, следует руководствоваться главным образом удобочитаемостью. Реляционное выражение часто соответствует одному прямому сравнению. Реляционный шаблон состоит из других шаблонов и подходит естественно, когда несколько диапазонов сопоставляются с переключением результатов.
Объединяйте условия с помощью логических шаблонов
Логические шаблоны объединяют или отрицают шаблоны с помощью операторов шаблонов and, or и not:
- Шаблон
andсовпадает при совпадении обоих вложенных шаблонов. - Шаблон
orсовпадает, если совпадает любой из вложенных шаблонов. - Шаблон
notуспешно срабатывает, когда его вложенный шаблон не срабатывает.
В открывшемся примере используется and для описания диапазона и or описания альтернативных вариантов. Шаблон not может исключить значение, как и в status is not Status.Complete. Следующие методы показывают обе формы, чтобы узнать их синтаксис и сравнить, как они выражают один и тот же тест:
static bool IsWeekendPattern(DayOfWeek day) =>
day is DayOfWeek.Saturday or DayOfWeek.Sunday;
static bool IsWeekendImperative(DayOfWeek day) =>
day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;
Шаблонная форма использует два константных шаблона, соединённых с помощью or. Форма императива использует два выражения равенства, соединённые оператором условного ИЛИ ||. Обе формы являются краткими и понятными для этого одного условия. Выберите форму, которая лучше всего подходит для окружающего кода. Шаблоны часто уточняют несколько связанных вариантов в примере switch, как в открываемом примере.
Операторы шаблонов формируют шаблоны, а не логические выражения: and соответствуют сочетанию шаблонов, or альтернативным шаблонам и not отрицанию шаблона. В логических выражениях используются &&, || и !. Выберите or , когда несколько альтернативных шаблонов имеют одинаковый результат. Выбор not при выражении исключенного шаблона является более понятным, чем перечисление каждого принятого значения.
Групповые шаблоны с скобками
Шаблон в скобках использует скобки, чтобы показать или изменить способ группировки вложенных шаблонов. Связывание определяет, какие операнды шаблона оператор группирует вместе, аналогично неявной группировке, когда скобки не ставятся. C# указывает следующий порядок привязки:
notandor
Следующий тест принимает приоритеты от 1 до 3 или специального приоритета 9:
static bool IsAcceptedPriority(int priority) =>
priority is (>= 1 and <= 3) or 9;
Компилятор группирует and перед or. Скобки явно показывают подразумеваемую группировку и позволяют легко увидеть два варианта: диапазон от 1 до 3 или число 9. Для удобочитаемости используйте круглые скобки всякий раз, когда в шаблоне сочетаются and и or, или когда not применяется к составному шаблону. Круглые скобки также могут изменять группирование по умолчанию, как и в not (>= 1 and <= 3).
Порядок проверок во время выполнения для вложенных шаблонов не определён, а операторы шаблонов подчиняются правилам сопоставления с шаблоном, а не правилам сокращённого вычисления булевых выражений. Пишите вложенные шаблоны так, чтобы их результат не зависел от порядка проверок.
Использование охранника when для отдельного условия
Логические шаблоны лучше всего работают, если вложенные шаблоны описывают само входное значение. Сторожевое условие when — это дополнительное логическое условие для метки case или ветви switch. Используйте охранник, если решение также зависит от информации, отдельной от входных данных шаблона.
Следующее предупреждение зависит от температуры и отдельного isOutdoors значения:
static string GetHeatWarning(int temperature, bool isOutdoors) =>
temperature switch
{
> 35 when isOutdoors => "High heat outdoors",
> 35 => "High heat",
_ => "No heat warning"
};
Реляционный шаблон > 35 описывает temperature входные данные. Защитное условие when isOutdoors проверяет отдельное значение. Защитное условие также предпочтительнее, если для условия нужен вызов метода или логическое выражение, которое невозможно ясно выразить с помощью синтаксиса шаблонов.
Используйте реляционные и логические паттерны, когда они помогают нагляднее увидеть допустимые формы или значения входных данных, особенно в нескольких ветвях switch. Используйте обычное логическое выражение, когда оно проще задаёт непосредственное условие. Используйте защитное условие when, если выбор в switch зависит от отдельного значения или от условия, которое лучше выразить логическим выражением.