dotnet / dotnet/csharplang

Proposal: Extended property patterns

Open
#4,394 17 comments 47 reactions 1 assignee Claimed by @333fred View on GitHub
Implemented Needs ECMA Spec Proposal champion
Dominant language
C#
Stars
12.7k
Forks
1.1k
Avg merge
11h 1m
Merged PRs (30d)
3

Description

# Extended property patterns

* [x] Proposed
* [ ] Prototype: Not Started
* [ ] Implementation: Not Started
* [x] Specification: [extended-property-patterns.md
](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/extended-property-patterns.md)

## Summary
[summary]: #summary

Allow property subpatterns to reference nested members.

## Motivation
[motivation]: #motivation

As discussed in https://github.com/dotnet/csharplang/discussions/4114 when you want to match a child property, nesting another recursive pattern adds too much noise which will hurt readability with no real advantage.

## Detailed design
[design]: #detailed-design

### Semantics

A pattern of the form `{ Property1.Property2: pattern }` is exactly equivalent to `{ Property1: { Property2: pattern } }`.

This will include the null check for `Nullable` values as it is the case for the expanded form, so we only see the underlying type's members when we dot off of a property pattern.

Repeated member paths are allowed. Under the hood, such member accesses are simplified to be evaluated once.

### Syntax

Currently a `SubpatternSyntax` uses `NameColonSyntax` which is not able to hold a chain of identifiers.

There are several avenues we could take:

1. **Accept a generic `ExpressoinSyntax` in place of the name**
This would particularly help with parsing and avoiding lookaheads, since patterns and expressions have a common parsing path, we can start with the pattern and if we get to a colon, we just adjust it as the name and continue to parse the actual pattern.
2. **Accept a generic `NameSyntax` in place of the name**
This seems to be the "correct" node to use, but is more expensive to parse. Also. if and when we introduce *indexer patterns* we probably want to relax property patterns to enable nesting those as well e.g. `{ Property1[0].Property2[1]: pattern }`. In that case we'll need to go with option (1) for forward compatibility.
3. **Accept a new `QualifiedNameColonSyntax` in addition to `NameColonSyntax`**
This option doesn't quite help with anything other than keeping the API consistent.

In the first two options, we're able to hold a simple identifier so we might want to consider deprecating `NameColon` API.

### Alternatives

We could use `{ P1?.P2: p }` syntax to make the implicit null check more apparent. But then we still want to consider `P1.P2` in case `?.` doesn't apply e.g. for structs. Since patterns shouldn't throw in regular usage and we should emit the null-check anyways, that distinction would seem to be unnecessary.

## Design meetings

- https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-02-10.md#extended-property-patterns

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.