# C# Language Design Meeting for January 22nd, 2025

## Agenda

- [Partial events and constructors](#partial-events-and-constructors)
- [Collection expression arguments](#collection-expression-arguments)
- [Extensions disambiguation syntax](#extensions-disambiguation-syntax)

## Quote of the Day

- Nothing particularly amusing or memorable today, sorry

## Discussion

### Partial events and constructors

Champion issue: https://github.com/dotnet/csharplang/issues/9058  
Specification: https://github.com/dotnet/csharplang/blob/305c5195ce36c9fe66e83235a15c5b9b885e77ab/proposals/partial-events-and-constructors.md

First up today, we did a very quick check in on partial events and constructors. When we looked at partial properties in C# 13,
we gave a brief consideration of the remaining member types, but decided to wait until we had use cases. We now have those use
cases, and we agree that they're sufficient motivation and validation to move forward with. We'll review the complete
specification at a later point, but this proposal is approved and moved into Working Set.

#### Conclusion

Approved, moved into Working Set

### Collection expression arguments

Champion issue: https://github.com/dotnet/csharplang/issues/8887  
Specification: https://github.com/dotnet/csharplang/blob/305c5195ce36c9fe66e83235a15c5b9b885e77ab/proposals/collection-expression-arguments.md#construction

Next, we took a look at some of the semantics around collection expression arguments. We did not go over syntax today; that will
be saved for a future LDM. Instead, we wanted to unblock the implementation's thornier semantic questions around overload
resolution. We had no comments on the standard constructor scenario; it seemed fine. What was more controversial were the second
and third scenarios. For the `Create` method scenario, there's a concern that some of the existing methods that the BCL would
want to use are not in the form that the proposal requires: some of them use `params`, so their collections are the last argument
to the `Create` method, not the first. While the BCL _could_ add another method that just reorders the parameters, we're not a
fan of the idea; we may want to relax the requirements here to allow those methods. We then looked at interface implementations,
and whether we want to expose "constructors" for collection expressions target-typed to these interface types. Unfortunately, one
thing that came during discussion here is a discrepancy in the checked-in specification and the notes; the notes from
[August 9th](../2023/LDM-2023-08-09.md#target-typing-of-collection-expressions-to-core-interfaces) indicate that we don't guarantee
what the underlying type of these interfaces is, while the checked-in specification appears to reflect an older initial approach
from the working group that guaranteed the concrete type to be `List<T>`. We didn't fully debate the implications of this
discrepancy on the current proposal, but the LDM did tend to lean either towards exposing the underlying constructors of the used
type, or to simply stating that a few constructors were presumed to exist, regardless of the underlying type that ends up being
used. For now, the group will proceed in that direction, and we'll need to bring this back again for further discussion to confirm.
Finally, we thought briefly about `dynamic` arguments; we don't see any current use cases, and think that there are going to be
some particularly gnarly challenges (for example, if we allow `Create` methods to have the collection either before or after the
other arguments, how does that impact dynamic binding?). Given this, we will block it for now.

#### Conclusion

Constructor rules are approved. `Create` rules are approved, with some caveats that we may need to bring back a looser version
after we do more investigation in the BCL for `Create` methods we want to approve. The implementation will proceed with interface
constructors for now, but will need to come back to ratify the decision and determine exactly how this works in the future.
`dynamic` arguments are disallowed.

### Extensions disambiguation syntax

Champion issue: https://github.com/dotnet/csharplang/issues/8697  
Specification: https://github.com/dotnet/csharplang/blob/e145230405eabef04a460003a20825fecce7f4d5/proposals/extensions.md  
Syntax examples: https://github.com/dotnet/csharplang/blob/8e5e055737bf8f278adf79176fdd370708e23d23/meetings/working-groups/extensions/disambiguation-syntax-examples.md

In our last topic for the day, we dived right into syntax options for disambiguating extension types.
[Last time](LDM-2025-01-06.md#extensions) we talked about syntax, we decided we wanted to explore member-focused approaches, and
see what that ended up looking like. Now we're back with the results of those explorations, and it runs into a few problems.
Specifically, there are some types of members that just don't have existing ways of being referred to in C#. For example,
indexers, constructors, operators, and casts cannot be captured into method references today, and we'd have to invent a new
syntax to even permit them to be referenced. This causes the member-focused approach to be fairly heavy-weight; it's a big piece
of new syntax for a scenario we don't expect will be used much. One possible view is that this syntax could be viewed more broadly;
what if we were to use this syntax to allow taking references to members that cannot be referenced today? That would bring
unification to the feature and help justify the weight of the new syntax forms. However, we're not certain that this is a road
we want to go down, and are wary of even more scope creep on the extensions feature. We're pretty split on this approach.

We then looked at the other example forms that were brought. The LDM is fairly split on the casting form; some think it's a natural
extension, others think that it's too far removed from the existing meaning of casting, as it does not modify the receiver.
Additionally, there is no real opportunity for a cast-like syntax to be useful to other disambiguation scenarios, such as calling
a DIM or an explicit implementation on a `struct` without boxing. Invocation-like syntax was more positively received, as was
`in` and `at`. `using` was pretty strongly disliked for introducing yet _another_ new meaning for `using`, which is already
heavily overloaded. `@` was also concerning for what impacts it could have on other tooling ecosystems such as Razor.

We did consider a couple more approaches that were not in the document as well:

* Could we allow `using MyExtension { range.Where (i => i < 10); }`? This is not a _new_ meaning for `using`, it's just a new
  location that an existing import syntax can be used. This is still potentially quite confusing, however, so we're not
  enamored with it.
* What if we just leaned into the static-method nature and just required disambiguation to call using the emitted name. For
  example, `range = MyExtension.op_Plus(range, 5);`. This has the advantage of requiring absolutely no new syntax, but does mean
  that we need to lean further into the "this is just sugar over static methods" approach.

Ultimately, we did not make a final decision today. We've expressed some initial opinions, and will come back later with
refinements. Ultimately, we do not think an initial preview of extensions is gated on this decision, so we are fine with not
having a concrete syntax today.
