Proposal: Extended property patterns · Issue #4394 · dotnet/csharplang (original) (raw)
Extended property patterns
- Proposed
- Prototype: Not Started
- Implementation: Not Started
- Specification: extended-property-patterns.md
Summary
Allow property subpatterns to reference nested members.
Motivation
As discussed in #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
Semantics
A pattern of the form { Property1.Property2: pattern }
is exactly equivalent to { Property1: { Property2: pattern } }
.
This will include the null check for Nullable<T>
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:
- 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. - 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. - Accept a new
QualifiedNameColonSyntax
in addition toNameColonSyntax
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.