11 Шаблонов и сопоставления шаблонов
11.1 Общие
Шаблон — это синтаксическая форма, которая может использоваться с is
оператором (§12.12.12) и в switch_statement (§13.8.3) для выражения формы данных, с которыми следует сравнивать входящие данные. Шаблон проверяется на выражение инструкции switch или на relational_expression, которая находится в левой части оператора, каждая из которых называется входным значением is
шаблона.
Формы шаблонов 11.2
11.2.1 Общие
Шаблон может иметь одну из следующих форм:
pattern
: declaration_pattern
| constant_pattern
| var_pattern
;
Declaration_pattern и var_pattern могут привести к объявлению локальной переменной.
Каждая форма шаблона определяет набор типов входных значений, к которым может применяться шаблон. Шаблон P
применяется к типу T
, если T
относится к типам, значения которых могут соответствовать шаблону. Это ошибка во время компиляции, если шаблон отображается в программе для сопоставления входного значения шаблона P
(§11.1) типа T
, если P
к нему неприменимо T
.
Пример. В следующем примере возникает ошибка во время компиляции, так как тип времени компиляции
v
имеет значениеTextReader
. Переменная типаTextReader
никогда не может иметь значение, совместимое со ссылкой:string
TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }
Однако следующее не создает ошибку во время компиляции, так как тип времени компиляции
v
имеет значениеobject
. Переменная типаobject
может иметь значение, совместимое со ссылкой:string
object v = Console.In; if (v is string s) { // code assuming v is a string }
пример конца
Каждая форма шаблона определяет набор значений, для которых шаблон соответствует значению во время выполнения.
Шаблон объявления 11.2.2
Declaration_pattern используется для проверки того, что значение имеет заданный тип и, если тест успешно выполнен, укажите значение в переменной этого типа.
declaration_pattern
: type simple_designation
;
simple_designation
: single_variable_designation
;
single_variable_designation
: identifier
;
Тип среды выполнения значения проверяется на тип в шаблоне, используя те же правила, указанные в операторе is-type (§12.12.12.12.1). Если тест выполнен успешно, шаблон соответствует указанному значению. Это ошибка во время компиляции, если тип является типом значения, допускающего значение NULL (§8.3.12). Эта форма шаблона никогда не соответствует значению null
.
Примечание. Выражение
e is T
is-type и шаблонe is T _
объявления эквивалентны, еслиT
не является пустым. конечная заметка
Учитывая входное значение шаблона (_
может находиться в области видимости в этот момент, эта именованная переменная не используется в этом контексте.) Если simple_designation является любым другим идентификатором, то вводится локальная переменная (§9.2.9.1) заданного типа, названной заданным идентификатором. Эта локальная переменная назначается значение входного значения шаблона, если шаблон соответствует значению.
Некоторые сочетания статического типа входного значения шаблона и заданного типа считаются несовместимыми и приводят к ошибке во время компиляции. Значение статического типаE
, как утверждается, совместимо с типомT
, если существует преобразование удостоверений, неявное или явное преобразование ссылок, преобразование бокса или распаковка преобразования из E
T
, или если E
T
или является открытым типом (§8.4.3). Шаблон объявления, именующий тип T
, применим к каждому типу E
, для которого E
совместим T
шаблон.
Примечание. Поддержка открытых типов может оказаться наиболее полезной при проверке типов, которые могут быть либо структурой, либо типами классов, а бокс следует избежать. конечная заметка
Пример. Шаблон объявления полезен для выполнения тестов типов времени выполнения ссылочных типов и заменяет идиом
var v = expr as Type; if (v != null) { /* code using v */ }
с немного более кратким
if (expr is Type v) { /* code using v */ }
пример конца
Это ошибка, если тип является типом значения, допускающего значение NULL.
Пример. Шаблон объявления можно использовать для проверки значений типов, допускающих значение NULL: значение типа (или поля
Nullable<T>
) соответствует шаблонуT
типаT2 id
, если значение не равно null иT2
имеетT
значение, или какой-либо базовый тип или интерфейсT
. Например, в фрагменте кодаint? x = 3; if (x is int v) { /* code using v */ }
Условие инструкции
if
находитсяtrue
во время выполнения, а переменнаяv
содержит значение3
типаint
внутри блока. пример конца
11.2.3 Константный шаблон
Constant_pattern используется для проверки значения входного значения шаблона (§11.1) с заданным константным значением.
constant_pattern
: constant_expression
;
Шаблон константы применим к типу, если существует неявное преобразование из константного P
T
Для константного шаблона P
преобразованное значение равно
- Если тип входного значения шаблона является целочисленным или типом перечисления, значение константы шаблона преобразуется в этот тип; иначе
- Если тип входного значения шаблона — это версия целочисленного типа или типа перечисления, константное значение шаблона, преобразованное в его базовый тип; иначе
- значение константы шаблона.
Учитывая входное значение шаблона e и константный шаблон P
с преобразованным значением v,
-
Значение e, если имеет целочисленный тип или тип перечисления, или пустую форму одного из них, и v имеет целочисленный тип, шаблон
P
соответствует значению e, если результат выраженияe == v
имеетtrue
значение ; в противном случае - Шаблон
P
соответствует значению e, если возвращаетсяobject.Equals(e, v)
.true
Пример. Оператор
switch
в следующем методе использует пять постоянных шаблонов в метках регистра.static decimal GetGroupTicketPrice(int visitorCount) { switch (visitorCount) { case 1: return 12.0m; case 2: return 20.0m; case 3: return 27.0m; case 4: return 32.0m; case 0: return 0.0m; default: throw new ArgumentException(...); } }
пример конца
Шаблон Var 11.2.4
Var_pattern соответствует каждому значению. То есть операция сопоставления шаблонов с var_pattern всегда выполняется успешно.
Var_pattern применимо к каждому типу.
var_pattern
: 'var' designation
;
designation
: simple_designation
;
Учитывая входное значение шаблона (§11.1) e, если обозначение является идентификатором _
, это обозначает отброс (§9.2.9.2), и значение e не связано ни с чем. (Хотя объявленная переменная с таким именем может находиться в области действия в данной точке, эта именованная переменная не рассматривается в этом контексте.) Если обозначение является другим идентификатором, то в процессе выполнения значение e привязано к недавно введенной локальной переменной (§9.2.9.1) с таким именем, тип которой является статическим типом e, а входное значение шаблона назначается этой локальной переменной.
Это ошибка, если имя var
привязывается к типу, в котором используется var_pattern .
11.3 Подсемпция шаблона
В инструкции switch это ошибка, если шаблон дела подмечен предыдущим набором незащищенных случаев (§13.8.3). В неофициальном порядке это означает, что любое входное значение было бы сопоставлено одним из предыдущих случаев. Следующие правила определяют, когда набор шаблонов подмножет заданный шаблон:
Шаблон P
будет соответствовать константеK
, если спецификация для поведения среды выполнения этого шаблона соответствуетP
K
.
Набор шаблонов Q
подменимирует шаблон P
, если какое-либо из следующих условий хранится:
-
P
— это константный шаблон, и любой из шаблонов в набореQ
будет соответствоватьP
преобразованном значению. -
P
— это шаблон var, и набор шаблоновQ
является исчерпывающимnull
. -
P
— это шаблон объявления с типом, и набор шаблоновT
являетсяQ
для типаT
(§11.4).
11.4. Исчерпывающая схема
Неформальным образом набор шаблонов является исчерпывающим для типа, если для каждого возможного значения этого типа, отличного от NULL, применяется некоторый шаблон в наборе. Следующие правила определяют, когда набор шаблонов является исчерпывающим для типа:
Набор шаблонов Q
является исчерпывающимT
:
-
T
является целочисленным или типом перечисления или версией, допускающей значение NULL, и для каждого из возможных значенийT
базового типа, не допускающего значения NULL, некоторые шаблоны будутQ
соответствовать значению этого значения; или - Некоторые шаблоны в
Q
шаблоне var; или - Некоторые шаблоны в
Q
шаблонеD
Пример:
static void M(byte b) { switch (b) { case 0: case 1: case 2: ... // handle every specific value of byte break; // error: the pattern 'byte other' is subsumed by the (exhaustive) // previous cases case byte other: break; } }
пример конца
ECMA C# draft specification