# C# Language Design Meeting for March 9th, 2026

## Agenda

- [Extension indexers](#extension-indexers)
    - [Ordering for implicit indexers and list patterns](#ordering-for-implicit-indexers-and-list-patterns)
    - [Slice extensions for range access](#slice-extensions-for-range-access)
    - [Spread optimization in collection expressions](#spread-optimization-in-collection-expressions)

## Quote(s) of the Day

- "Ordering or orering?" "I'm writing ordering, sorry if that confuses you"

## Discussion

### Extension indexers

Champion issue: https://github.com/dotnet/csharplang/issues/9856  
Spec: https://github.com/dotnet/csharplang/blob/ee06dd0eaaff1ddb16d0f6680107a1a00aecee92/proposals/extension-indexers.md

We continued discussion of the remaining open questions around extension indexers and their interactions with list patterns. The
core tension is that multiple lookup principles all seem desirable in isolation: instance members should continue to beat extensions
for compatibility, inner extension scopes should generally beat outer scopes, and real `this[Index]`/`this[Range]` members are
usually preferable to implicit indexers assembled from `Length` or `Count` together with `this[int]` or `Slice`. Unfortunately,
these preferences conflict once extension members are allowed to contribute to indexing.

#### Ordering for implicit indexers and list patterns

The hardest question was how to order extension lookup once implicit indexers are involved. We compared two broad
approaches. One would continue to prioritize inner extension scopes over outer scopes, even when that meant selecting an
implicit indexer assembled from closer members instead of a real indexer found farther out. The other would keep the strong
preference that instance members always beat extensions, but once extension lookup was required it would give a weak priority
to real indexers over implicit ones, even if the real indexer came from an outer extension scope.

We chose the second ordering. We feel that a real indexer remains a more coherent single declaration than an implicit indexer
assembled from multiple members, and that this weak preference was worth preserving once the search had already moved beyond
instance members. This does make extension lookup somewhat irregular, because the language will no longer uniformly prefer the
closest extension-provided solution in every case, but the LDM preferred that irregularity over a rule that would make real
extension indexers lose to extension-based implicit combinations more often.

List patterns were discussed alongside ordinary indexer access. We do not want list patterns to use one `Length` or
`Count` member for shape checking and then silently use a different one when resolving indexing behavior. Instead, list pattern
support should be described in terms of independently resolving the members needed for the operation, using the same overall
ordering principles as indexer access.

We workshopped the following specese during the meeting, which will need to be refined before inclusion in the speclet:

> 1. List patterns are resolved as if we look for Length/Count, Index indexer and Range indexer individually
> 2. For Index and Range indexers, proceed as follows:
>     a. With instance lookup only, find the "real" index if possible
>     b. With instance lookup only, find the parts of the implicit indexer if possible
>     c. With full lookup (instance+extension), find the "real" index if possible
>     d. With full lookup (instance+extension), find the parts of the implicit indexer if possible (each in individual lookups)

##### Conclusion

When resolving extension-based indexing behavior, instance lookup remains strictly better than extension lookup. After that,
the language will give a weak preference to real `Index` and `Range` indexers over implicit indexers, even when that means an
outer extension scope can beat an implicit solution formed from a closer scope. List patterns will resolve the required
members using the same overall ordering model rather than treating implicit indexers in extensions as unsupported.

#### Slice extensions for range access

We next looked at the `Slice` portion of implicit range support. The question was whether, once extension members are
allowed to contribute, only extension-block `Slice` members should count, or whether classic extension methods named `Slice`
should count as well. Historically, neither form contributed here, so enabling extension participation would cause some code
to start compiling where it previously produced an error.

We see no good reason to distinguish the two forms. The extensions feature has consistently tried to make classic
extension members and extension-block members interchangeable from the user's point of view, and this scenario should follow
that same principle. Moving from an error to a successful binding was also considered acceptable here, because it does not
break previously-working code and is a natural consequence of allowing extensions to participate in range access.

##### Conclusion

Both classic extension `Slice` methods and extension-block `Slice` members will contribute to implicit range access under the
new rules.

#### Spread optimization in collection expressions

Finally, we considered whether extension `Length` or `Count` properties should participate in the optimization for spread
elements in collection expressions. That optimization exists to avoid unnecessary reallocations by pre-sizing the destination
when the compiler can cheaply determine the number of elements that will be produced.

The concern was that an extension `Length` or `Count` member is much less likely to represent cheap, intrinsic knowledge about
the underlying type. In many cases, such an extension would have to enumerate the source to discover the count, which would
defeat the purpose of the optimization by adding an extra traversal before the actual spread occurs. We therefore
prefer to keep the optimization tied to information directly exposed by the source type itself. If compelling scenarios
emerge later, or if there is a better hook for efficient optional counts, the language can revisit this decision.

##### Conclusion

Extension `Length` and `Count` members will not participate in spread optimization for collection expressions.
