You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Edits suggested for patterns
Respond to the comments from the committee on the first take at patterns.
* Use the rules for `is type` for the type pattern
The rules to determine if an `is` expression returns true are the same as determine if the `is` pattern matches. Also, added a note that the result is the same for a declaration pattern with a discard when the type isn't nullable.
* respond to review comments
* Update standard/expressions.md
* Update standard/patterns.md
Co-authored-by: Jon Skeet <[email protected]>
---------
Co-authored-by: Jon Skeet <[email protected]>
Copy file name to clipboardExpand all lines: standard/classes.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4946,7 +4946,7 @@ A *static_constructor_declaration* may include a set of *attributes* ([§22](att
4946
4946
4947
4947
The *identifier* of a *static_constructor_declaration* shall name the class in which the static constructor is declared. If any other name is specified, a compile-time error occurs.
4948
4948
4949
-
When a static constructor declaration includes an `extern` modifier, the static constructor is said to be an ***external static constructor***. Because an external static constructor declaration provides no actual implementation, its *static_constructor_body* consists of a semicolon. For all other static constructor declarations, the *static_constructor_body* consists of either
4949
+
When a static constructor declaration includes an `extern` modifier, the static constructor is said to be an ***external static constructor***. Because an external static constructor declaration provides no actual implementation, its *static_constructor_body* consists of a semicolon. For all other static constructor declarations, the *static_constructor_body* consists of either
4950
4950
4951
4951
- a *block*, which specifies the statements to execute in order to initialize the class; or
4952
4952
- an expression body, which consists of `=>` followed by an *expression* and a semicolon, and denotes a single expression to execute in order to initialize the class.
Copy file name to clipboardExpand all lines: standard/expressions.md
+13-11Lines changed: 13 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2160,7 +2160,7 @@ A *null_conditional_element_access* expression `E` is of the form `P?[A]B`; wher
2160
2160
((object)P==null) ?null:P[A]B
2161
2161
```
2162
2162
2163
-
Exceptthat `P` isevaluatedonlyonce.
2163
+
Exceptthat `P` isevaluatedonlyonce.
2164
2164
2165
2165
> *Note*:Inanexpressionoftheform:
2166
2166
>
@@ -4019,6 +4019,8 @@ equality_expression
4019
4019
;
4020
4020
```
4021
4021
4022
+
> *Note*: Lookup for the right operand of the `is` operator must first test as a *type*, then as an *expression* which may span multiple tokens. In the case where the operand is an *expreesion*, the pattern expression must have precedence at least as high as *shift_expression*. *end note*
4023
+
4022
4024
The `is` operator is described in [§12.12.12](expressions.md#121212-the-is-operator) and the `as` operator is described in [§12.12.13](expressions.md#121213-the-as-operator).
4023
4025
4024
4026
The `==`, `!=`, `<`, `>`, `<=` and `>=` operators are ***comparison operators***.
@@ -4378,16 +4380,16 @@ The tuple equality operator `x != y` is evaluated as follows:
4378
4380
4379
4381
### 12.12.12 The is operator
4380
4382
4381
-
There are two forms of the `is` operator. One is the *is-type operator*, which has a type on the right-hand-side. The other is the *is-pattern operator*, which has a pattern on the right-hand-side.
4383
+
There are two forms of the `is` operator. One is the *is-type operator*, which has a type on the right-hand-side. The other is the *is-pattern operator*, which has a pattern on the right-hand-side.
4382
4384
4383
4385
#### 12.12.12.1 The is-type operator
4384
4386
4385
4387
The *is-type operator* is used to check if the run-time type of an object is compatible with a given type. The check is performed at runtime. The result of the operation `E is T`, where `E` is an expression and `T` is a type other than `dynamic`, is a Boolean value indicating whether `E` is non-null and can successfully be converted to type `T` by a reference conversion, a boxing conversion, an unboxing conversion, a wrapping conversion, or an unwrapping conversion.
4386
4388
4387
4389
The operation is evaluated as follows:
4388
4390
4389
-
1. If `E` is an anonymous function, a compile-time error occurs
4390
-
1. If `E` is a method group or the `null` literal, of if the value of `E` is `null`, the result is `false`.
4391
+
1. If `E` is an anonymous function or method group, a compile-time error occurs
4392
+
1. If `E` is the `null` literal, or if the value of `E` is `null`, the result is `false`.
4391
4393
1. Otherwise:
4392
4394
1. Let `R` be the runtime type of `E`.
4393
4395
1. Let `D` be derived from `R` as follows:
@@ -4804,7 +4806,7 @@ If `ref` is present:
4804
4806
If `ref` is not present, the second and third operands, `x` and `y`, of the `?:` operator control the type of the conditional expression:
4805
4807
4806
4808
- If `x` has type `X` and `y` has type `Y` then,
4807
-
- If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.15](expressions.md#126315-finding-the-best-common-type-of-a-set-of-expressions)). If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples.
4809
+
- If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.15](expressions.md#126315-finding-the-best-common-type-of-a-set-of-expressions)). If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples.
4808
4810
- Otherwise, if an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from `X` to `Y`, but not from `Y` to `X`, then `Y` is the type of the conditional expression.
4809
4811
- Otherwise, if an implicit enumeration conversion ([§10.2.4](conversions.md#1024-implicit-enumeration-conversions)) exists from `X` to `Y`, then `Y` is the type of the conditional expression.
4810
4812
- Otherwise, if an implicit enumeration conversion ([§10.2.4](conversions.md#1024-implicit-enumeration-conversions)) exists from `Y` to `X`, then `X` is the type of the conditional expression.
@@ -4903,7 +4905,7 @@ When recognising an *anonymous_function_body* if both the *null_conditional_invo
4903
4905
<!-- markdownlint-disable MD028 -->
4904
4906
4905
4907
<!-- markdownlint-enable MD028 -->
4906
-
> *Example*: The result type of `List<T>.Reverse` is `void`. In the following code, the body of the anonymous expression is a *null_conditional_invocation_expression*, so it is not an error.
4908
+
> *Example*: The result type of `List<T>.Reverse` is `void`. In the following code, the body of the anonymous expression is a *null_conditional_invocation_expression*, so it is not an error.
Copy file name to clipboardExpand all lines: standard/lexical-structure.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Conforming implementations shall accept Unicode compilation units encoded with t
16
16
<!-- markdownlint-disable MD028 -->
17
17
18
18
<!-- markdownlint-enable MD028 -->
19
-
> *Note*: It is beyond the scope of this specification to define how a file using a character representation other than Unicode might be transformed into a sequence of Unicode characters. During such transformation, however, it is recommended that the usual line-separating character (or sequence) in the other character set be translated to the two-character sequence consisting of the Unicode carriage-return character (U+000D) followed by Unicode line-feed character (U+000A). For the most part this transformation will have no visible effects; however, it will affect the interpretation of verbatim string literal tokens ([§6.4.5.6](lexical-structure.md#6456-string-literals)). The purpose of this recommendation is to allow a verbatim string literal to produce the same character sequence when its compilation unit is moved between systems that support differing non-Unicode character sets, in particular, those using differing character sequences for line-separation. *end note*
19
+
> *Note*: It is beyond the scope of this specification to define how a file using a character representation other than Unicode might be transformed into a sequence of Unicode characters. During such transformation, however, it is recommended that the usual line-separating character (or sequence) in the other character set be translated to the two-character sequence consisting of the Unicode carriage-return character (U+000D) followed by Unicode line-feed character (U+000A). For the most part this transformation will have no visible effects; however, it will affect the interpretation of verbatim string literal tokens ([§6.4.5.6](lexical-structure.md#6456-string-literals)). The purpose of this recommendation is to allow a verbatim string literal to produce the same character sequence when its compilation unit is moved between systems that support differing non-Unicode character sets, in particular, those using differing character sequences for line-separation. *end note*
20
20
21
21
## 6.2 Grammars
22
22
@@ -72,7 +72,7 @@ If a sequence of tokens can be parsed (in context) as a *simple_name* ([§12.8.4
72
72
- Acontextualquerykeywordappearinginsideaqueryexpression; or
73
73
- Incertaincontexts, *identifier* istreatedasadisambiguatingtoken. Thosecontextsarewherethesequenceoftokensbeingdisambiguatedisimmediatelyprecededbyoneofthekeywords `is`, `case` or `out`, orariseswhileparsingthefirstelementofatupleliteral (inwhichcasethetokensareprecededby `(` or `:` andtheidentifierisfollowedbya `,`) orasubsequentelementofatupleliteral.
74
74
75
-
Ifthefollowingtokenisamongthislist, oranidentifierinsuchacontext, thenthe*type_argument_list*isretainedaspartofthe *simple_name*, *member_access*or*pointer_member-access*andanyotherpossibleparseofthesequenceoftokensisdiscarded. Otherwise, the*type_argument_list*isnotconsideredtobepartofthe *simple_name*, *member_access*or*pointer_member_access*, evenifthereisnootherpossibleparseofthesequenceoftokens. (Theserulesarenotapplied when parsing a *type_argument_list* in a *namespace_or_type_name* [§7.8](basic-concepts.md#78-namespace-and-type-names).)
75
+
Ifthefollowingtokenisamongthislist, oranidentifierinsuchacontext, thenthe*type_argument_list*isretainedaspartofthe *simple_name*, *member_access*or*pointer_member-access*andanyotherpossibleparseofthesequenceoftokensisdiscarded. Otherwise, the*type_argument_list*isnotconsideredtobepartofthe *simple_name*, *member_access*or*pointer_member_access*, evenifthereisnootherpossibleparseofthesequenceoftokens. (Theserulesarenotapplied when parsing a *type_argument_list* in a *namespace_or_type_name* [§7.8](basic-concepts.md#78-namespace-and-type-names).)
76
76
77
77
>*Note*: Theserulesarenotapplied when parsing a *type_argument_list* in a *namespace_or_type_name* ([§7.8](basic-concepts.md#78-namespace-and-type-names)). *end note*
Copy file name to clipboardExpand all lines: standard/patterns.md
+13-10Lines changed: 13 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,9 +20,9 @@ pattern
20
20
21
21
A *declaration_pattern* and a *var_pattern* can result in the declaration of a local variable.
22
22
23
-
Each pattern form defines the set of types for input values that the pattern may be applied to. A pattern `P` is *applicable to* a type `T` if `T` is among the types whose values the pattern may match. It is an error if a pattern `P` appears in a program to match a pattern input value ([§11.1](patterns.md#111-general)) of type `T` if `P` is not applicable to `T`.
23
+
Each pattern form defines the set of types for input values that the pattern may be applied to. A pattern `P` is *applicable to* a type `T` if `T` is among the types whose values the pattern may match. It is a compile-time error if a pattern `P` appears in a program to match a pattern input value ([§11.1](patterns.md#111-general)) of type `T` if `P` is not applicable to `T`.
24
24
25
-
Each pattern form defines the set of values for which the pattern *matches* the value.
25
+
Each pattern form defines the set of values for which the pattern *matches* the value at runtime.
26
26
27
27
### 11.2.2 Declaration pattern
28
28
@@ -40,11 +40,13 @@ single_variable_designation
40
40
;
41
41
```
42
42
43
-
The runtime type of the value is tested against the *type* in the pattern. If it is of that runtime type (or some subtype), the pattern *matches* that value. This pattern form never matches a `null` value.
43
+
The runtime type of the value is tested against the *type* in the pattern using the same rules specified in the is-type operator (§12.12.12.1). If the test succeeds, the pattern *matches* that value. It is a compile-time error if the *type* is a nullable value type (§8.3.12). This pattern form never matches a `null` value.
44
+
45
+
> *Note*: The is-type expression `e is T` and the declaration pattern `e is T _` are equivalent when `T` isn't a nullable type. *end note*
44
46
45
47
Given a pattern input value ([§11.1](patterns.md#111-general)) *e*, if the *simple_designation* is the *identifier*`_`, it denotes a discard ([§9.2.9.1](variables.md#9291-discards)) and the value of *e* is not bound to anything. (Although a declared variable with the name `_` may be in scope at that point, that named variable is not seen in this context.) If *simple_designation* is any other identifier, a local variable ([§9.2.9](variables.md#929-local-variables)) of the given type named by the given identifier is introduced. That local variable is assigned the value of the pattern input value when the pattern *matches* the value.
46
48
47
-
Certain combinations of static type of the pattern input value and the given type are considered incompatible and result in a compile-time error. A value of static type `E` is said to be ***pattern compatible*** with the type `T` if there exists an identity conversion, an implicit reference conversion, a boxing conversion, an explicit reference conversion, or an unboxing conversion from `E` to `T`, or if either `E` or `T` is an open type ([§8.4.3](types.md#843-open-and-closed-types)). A declaration pattern naming a type `T` is *applicable to* every type `E` for which `E` is pattern compatible with `T`.
49
+
Certain combinations of static type of the pattern input value and the given type are considered incompatible and result in a compile-time error. A value of static type `E` is said to be ***pattern compatible*** with the type `T` if there exists an identity conversion, an implicit or explicit reference conversion, a boxing conversion, or an unboxing conversion from `E` to `T`, or if either `E` or `T` is an open type ([§8.4.3](types.md#843-open-and-closed-types)). A declaration pattern naming a type `T` is *applicable to* every type `E` for which `E` is pattern compatible with `T`.
48
50
49
51
> *Note*: The support for open types can be most useful when checking types that may be either struct or class types, and boxing is to be avoided. *end note*
50
52
<!-- markdownlint-disable MD028 -->
@@ -90,22 +92,23 @@ A constant pattern `P` is *applicable to* a type `T` if there is an implicit con
90
92
91
93
For a constant pattern `P`, its *converted value* is
92
94
93
-
- if the input expression’s type is an integral type or an enum type, the pattern’s constant value converted to that type; otherwise
94
-
- if the input expression’s type is the nullable version of an integral type or an enum type, the pattern’s constant value converted to its underlying type; otherwise
95
+
- if the pattern input value’s type is an integral type or an enum type, the pattern’s constant value converted to that type; otherwise
96
+
- if the pattern input value’s type is the nullable version of an integral type or an enum type, the pattern’s constant value converted to its underlying type; otherwise
95
97
- the value of the pattern’s constant value.
96
98
97
99
Given a pattern input value *e* and a constant pattern `P` with converted value *v*,
98
100
99
101
- if *e* has integral type or enum type, or a nullable form of one of those, and *v* has integral type, the pattern `P`*matches* the value *e* if result of the expression `e == v` is `true`; otherwise
100
102
- the pattern `P`*matches* the value *e* if `object.Equals(e, v)` returns `true`.
101
103
102
-
> *Example*:
104
+
> *Example*: The `switch` statement in the following method uses five constant patterns in its case labels.
@@ -158,7 +161,7 @@ The following rules define when a set of patterns is *exhaustive* for a type:
158
161
159
162
A set of patterns `Q` is *exhaustive* for a type `T` if any of the following conditions hold:
160
163
161
-
1.`T` is an integral or enum type, or a nullable version of one of those, and for every possible value of `T`’s underlying type, some pattern in `Q` would match that value; or
164
+
1.`T` is an integral or enum type, or a nullable version of one of those, and for every possible value of `T`’s non-nullable underlying type, some pattern in `Q` would match that value; or
162
165
2. Some pattern in `Q` is a *var pattern*; or
163
166
3. Some pattern in `Q` is a *declaration pattern* for type `D`, and there is an identity conversion, an implicit reference conversion, or a boxing conversion from `T` to `D`.
0 commit comments