Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Tip
Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Если вы не знакомы с программированием, сначала начните с учебных пособий по началу работы. Опытные разработчики C# могут использовать ссылки на шаблоны для полного синтаксиса и правил.
Вы пришли из другого языка? Шаблоны C# служат ролью, аналогичной сопоставлению шаблонов Java и случаям Pythonmatch. В C# используются шаблоны в is выражениях, switch инструкциях и switch выражениях.
Сопоставление шаблонов применяет шаблон к выражению. Шаблон — это условие для проверки входного выражения. Ввод шаблона представляет собой это выражение. C# вычисляет входное выражение; Результатом является вычисляемое значение. Шаблон проверяет, имеет ли значение определённый тип, равно ли оно определённому значению или имеет определённую структуру. При совпадении шаблона код может использовать сведения, полученные тестом, например более конкретный тип или значение, извлеченные из объекта.
Шаблон можно использовать в трех контекстах:
- Справа от
isоператора. -
caseВ метке инструкцииswitch. - В ветви выражения
switch.
Шаблоны часто понятнее, чем последовательность выражений сравнения, так как каждая ветвь описывает данные, с которыми она работает. Например, следующий метод использует switch выражение для выбора сообщения доставки:
static string GetDeliveryMessage(Delivery? delivery) =>
delivery switch
{
null => "No delivery was scheduled.",
ExpressDelivery express => $"Express package {express.TrackingCode}",
StandardDelivery { Days: <= 2 } => "Standard delivery arriving soon",
_ => "Standard delivery"
};
Рекурсивные шаблоны имеют собственные входные выражения. В StandardDelivery { Days: <= 2 } внешний шаблон получает выражение delivery. Рекурсивный <= 2 шаблон получает Days выражение свойства из соответствующего StandardDelivery объекта.
Выражение, прежде чем switch является входным выражением. Каждая строка внутри фигурных скобок — это контакт переключателя. Шаблон отображается раньше =>, и результат появляется после него. C# вычисляет входное выражение, а затем выбирает первую по порядку ветвь в тексте, шаблон которой соответствует выражению и необязательное защитное условие when которой равно true. Необязательное when защитное условие — это дополнительное булево условие, которое записывается после шаблона. В предыдущем примере показаны следующие шаблоны:
-
null— это константный шаблон. Проверяет, вычисляется ли выражениеnullкакdelivery. -
ExpressDelivery express— это шаблон объявления с двумя частями.ExpressDelivery— это часть типовых испытаний. Проверяет, является ли вычисляемое значение объектом, не равным null, тип времени выполнения которого совместим сExpressDelivery.express— это обозначение переменной: она объявляет переменную с именемexpressи назначает ему соответствующийExpressDeliveryобъект. -
StandardDelivery { Days: <= 2 }начинается с проверки типа.StandardDeliveryпроверяет, является ли вычисляемое значение объектом, не допускающим значение NULL этого типа. Фигурные скобки содержат шаблон свойства.Daysприсваивает имя проверяемого свойства, поэтомуDaysвыражение свойства становится входными данными в рекурсивном шаблоне. Часть<= 2— это реляционный шаблон, который проверяет, что вычисляемое значение меньше либо равно2. -
_(символ подчеркивания) — это шаблон отбрасывания. Он соответствует каждому вычисленному значению, включаяnull. Поскольку предыдущие ветви уже обрабатываютnull, экспресс-доставки и стандартные доставки, поступающие в течение двух дней, эта последняя ветвь обрабатывает все остальные значения.
Рука без охранника whenне охраняется. Все руки в первом примере не охраняются. Если более ранняя ветвь без защитного условия соответствует каждому проверяемому значению, которому может соответствовать более поздняя ветвь, то более поздняя ветвь поглощается.
Поглощённый шаблон — это шаблон, для которого любое возможное входное значение, соответствующее ему, уже было сопоставлено более ранней веткой switch. Он никогда не может совпадать, поэтому компилятор сообщает об ошибке. Отбрасывающая ветвь (_) должна идти последней, так как она соответствует любому входному выражению. Защищенная рука не подменяет более позднюю руку на основе его шаблона только потому, что охранник может быть false.
Switch-выражение считается исчерпывающим, если его ветви обрабатывают все возможные входные значения. Первый пример является исчерпывающим, поскольку его последняя отбрасывающая ветка обрабатывает всё, что не соответствует ни одной из предыдущих веток. Компилятор предупреждает, когда обнаруживает потенциальное входное значение, которое не обрабатывается рукой. Компилятор не может доказать исчерпывающее значение для каждого сочетания шаблонов, но эта диагностика помогает создавать правильный код сопоставления шаблонов. Подробные сведения о правилах сопоставления, включения и полноты см. в справочнике по шаблонам.
Проверка одного условия с помощью is
Используйте оператор, is если требуется один логический тест. Следующий код вычисляет выражение delivery и применяет шаблон объявления ExpressDelivery express. Часть, относящаяся к типу, соответствует, если вычисляемое значение не является null, а его тип во время выполнения совместим с ExpressDelivery. Когда шаблон совпадает, его обозначение переменной объявляет express:
static void PrintTrackingCode(Delivery delivery)
{
if (delivery is ExpressDelivery express)
{
Console.WriteLine($"Track express package {express.TrackingCode}");
}
}
Компилятор отслеживает, назначена ли локальная переменная перед чтением кода. Такое отслеживание называется определённым присваиванием.
if Внутри этого блока условие может быть true только в том случае, если шаблон присвоил совпавший объект переменной express. Поэтому компилятор знает, что express определенно назначается там. Код может безопасно использовать его TrackingCode свойство. Вам не нужен отдельный приведение. Если вам нужен только тест типа и не нужно объявлять переменную, используйте шаблон типа, например delivery is ExpressDelivery.
Используйте is null или is not null для проверок NULL. Эти шаблоны не вызывают определяемые пользователем операторы == или !=.
static void PrintPackageStatus(Delivery? delivery)
{
if (delivery is null)
{
Console.WriteLine("No package is available.");
}
else
{
Console.WriteLine("A package is ready to track.");
}
}
Дополнительные рекомендации по безопасности null см. в разделе "Ссылочные типы, допускающие значение NULL".
Выберите между инструкцией и выражением
Шаблоны работают с обеими switchформами:
- Используйте
switchинструкцию, если для каждого совпадения нужно выполнить одну или несколько инструкций. - Используйте выражение
switch, когда каждое совпадение должно возвращать значение.
Приведённый ниже оператор switch сообщает об обновлении доставки. Ветвь экспресс-доставки записывает два сообщения, поэтому инструкция подходит естественно:
static void PrintDeliveryUpdate(Delivery? delivery)
{
switch (delivery)
{
case null:
Console.WriteLine("No delivery was scheduled.");
break;
case ExpressDelivery express:
Console.WriteLine($"Express delivery {express.TrackingCode} is ready.");
Console.WriteLine("Notify the priority desk.");
break;
case StandardDelivery standard:
Console.WriteLine($"Standard delivery arrives in {standard.Days} days.");
break;
default:
Console.WriteLine("Another delivery type is scheduled.");
break;
}
}
Каждая из них case применяет шаблон к выражению delivery . Соответствующий раздел может выполнять любое количество операторов перед break выходом из коммутатора. Раздел default обрабатывает всё, что не подпадает под предыдущие условия.
Следующее выражение коммутатора заменяет цепочку if / else if , которая назначает один результат:
static string GetStatusMessage(StandardDelivery delivery) =>
delivery.Days switch
{
0 => "Delivered today",
1 => "Arriving tomorrow",
<= 3 => "Arriving soon",
_ => "In transit"
};
Выражение переключателя является кратким, так как каждая рука имеет ту же цель: создает возвращаемое значение. Используйте инструкцию switch, когда ветви выполняют действия, и используйте switch-выражение, когда ветви вычисляют единственный результат.
Категории узоров
C# включает шаблоны для распространенных типов тестов данных:
| Категория шаблонов | Что он проверяет |
|---|---|
Объявление, константы и var шаблоны |
Тип времени выполнения, определенное константное значение или любое значение, которое требуется записать. |
| Шаблоны типов | Тип времени выполнения без объявления переменной |
| Свойства и позиционные шаблоны | Свойства, поля или деконструированные значения |
| Реляционные и логические шаблоны | Сравнения и сочетания, такие как and, orи not |
| Шаблоны списков | Значения и форма списка или массива |
| Отмена шаблонов и отмены | Любое оставшееся значение или значение, которое код намеренно игнорирует |
Статьи из раздела «Основы», ссылки на которые приведены в таблице, содержат материалы по категориям, описанным в этом разделе на данный момент. Полный синтаксис и примеры для всех категорий шаблонов см. в справочнике по шаблонам.