Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions standard/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,11 @@
;
subpattern
: pattern
| identifier ':' pattern
| subpattern_name ':' pattern
;
subpattern_name
: identifier
| subpattern_name '.' identifier
;
```

Expand Down Expand Up @@ -296,7 +300,7 @@
;
```

It is an error if any *subpattern* of a *property_pattern* does not contain an *identifier*.
It is an error if any *subpattern* of a *property_pattern* does not contain a *subpattern_name*.

It is a compile-time error if the *type* is a nullable value type ([§8.3.12](types.md#8312-nullable-value-types)) or a nullable reference type ([§8.9.3](types.md#893-nullable-reference-types)).

Expand All @@ -314,12 +318,18 @@
>
> *end note*

Given a match of an expression *e* to the pattern *type* `{` *subpatterns* `}`, it is a compile-time error if the expression *e* is not pattern-compatible with the type *T* designated by *type*. If the type is absent, the type is assumed to be the static type of *e*. Each of the identifiers appearing on the left-hand-side of its *subpatterns* shall designate an accessible readable property or field of *T*. If the *simple_designation* of the *property_pattern* is present, it declares a pattern variable of type *T*.
Given a match of an expression *e* to the pattern *type* `{` *subpatterns* `}`, it is a compile-time error if the expression *e* is not pattern-compatible with the type *T* designated by *type*. If the type is absent, the type is assumed to be the static type of *e*. Each *subpattern_name* appearing on the left-hand-side of its *subpatterns* shall designate an accessible readable property or field of *T*. If the *simple_designation* of the *property_pattern* is present, it declares a pattern variable of type *T*.

At runtime, the expression is tested against *T*. If this fails then the property pattern match fails, and the result is `false`. If it succeeds, then each *property_subpattern* field or property is read, and its value matched against its corresponding pattern. The result of the whole match is `false` only if the result of any of these is `false`. The order in which subpatterns are matched is not specified, and a failed match may not test all subpatterns at runtime. If the match succeeds and the *simple_designation* of the *property_pattern* is a *single_variable_designation*, the declared variable is assigned the matched value.

The *property_pattern* may be used to pattern-match with anonymous types.

A *subpattern_name* may reference a nested member. In such a case, the receiver for each name lookup is the type of the previous member *T₀*, starting from the *input type* of the *property_pattern*. If *T* is a nullable type, *T₀* is its underlying type, otherwise *T₀* is equal to *T*. For example, a pattern of the form `{ Prop1.Prop2: pattern }` is exactly equivalent to `{ Prop1: { Prop2: pattern } }`.

> *Note*: This will include the null check when *T* is a nullable value type or a reference type. This null check means that the nested properties available will be the properties of *T₀*, not of *T*. As repeated member paths are allowed, the compilation of pattern matching can take advantage of common parts of patterns. *end note*
<!-- markdownlint-disable MD028 -->

<!-- markdownlint-enable MD028 -->
> *Example*:
>
> <!-- Example: {template:"standalone-console", name:"PropertyPattern2", replaceEllipsis:true, customEllipsisReplacements: ["new object()", ";"], ignoredWarnings:["CS0642"]} -->
Expand All @@ -337,14 +347,14 @@
> <!-- Example: {template:"standalone-console", name:"PropertyPattern3", inferOutput:true} -->
> ```csharp
> Console.WriteLine(TakeFive("Hello, world!")); // output: Hello
> Console.WriteLine(TakeFive("Hi!")); // output: Hi!

Check warning on line 350 in standard/patterns.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/patterns.md#L350

MDC032::Line length 91 > maximum 81
> Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' })); // output: 12345
> Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' })); // output: abc
>
> static string TakeFive(object input) => input switch
> {
> string { Length: >= 5 } s => s.Substring(0, 5),
> string s => s,

Check warning on line 357 in standard/patterns.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/patterns.md#L357

MDC032::Line length 87 > maximum 81
> ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
> ICollection<char> symbols => new string(symbols.ToArray()),
> null => throw new ArgumentNullException(nameof(input)),
Expand Down
Loading