# C# Language Design Meeting for June 23rd, 2025

## Agenda

- [Extensions](#extensions)
    - [Use of extension operators in LINQ expression trees](#use-of-extension-operators-in-linq-expression-trees)
    - [`ref` encoding and conflict checks](#ref-encoding-and-conflict-checks)
    - [Extern support](#extern-support)
    - [Lookup](#lookup)

## Quote of the Day

- "So we pick the method" "But the spec says that should have been an ambiguity"
- "That can't be it, we have 20-odd minutes left in the meeting. That's illegal!"

## Discussion

### Extensions

Champion issue: https://github.com/dotnet/csharplang/issues/8697  
Specifications:
* https://github.com/dotnet/csharplang/blob/d9aac41d8b0ff4d2bb322ffb8f85a4a4a14690df/proposals/extensions.md
* https://github.com/dotnet/csharplang/blob/d9aac41d8b0ff4d2bb322ffb8f85a4a4a14690df/proposals/extension-operators.md

#### Use of extension operators in LINQ expression trees

Question: https://github.com/dotnet/csharplang/blob/main/proposals/extension-operators.md#use-of-extension-operators-in-linq-expression-trees

Previously, we'd decided to use the existing `Expression` factory methods for expression trees. This works in most cases, but
falls over in scenarios that need multiple extension operators, such as `&&` or `||`. For these scenarios, the ideal fix would
be to add a new factory method, but we don't think this is something that we can do at this time. Therefore, we'll simply note
the issue in documentation, and if we make future changes to expression trees, we could potentially address this shortcoming then.

##### Conclusion

Proposed rules approved. `&&` and `||` implemented via extensions will not be allowed in expression trees.

#### `ref` encoding and conflict checks

Question: https://github.com/dotnet/csharplang/blob/d9aac41d8b0ff4d2bb322ffb8f85a4a4a14690df/proposals/extensions.md#metadata

> Confirm that `ref` should not be included in extension type name

After some discussion here, we realized that the question has some fundamental issues that need to go back to the working group.
https://github.com/dotnet/roslyn/issues/79043 demonstrates an issue with our current conflict checking rules; because we do not
consider `ref`ness when doing signature conflict checking, we prevent this scenario from migrating to new extensions. We also
don't think this is particularly edge case code; it's certainly not mainstream, but it's not a truly niche thing. The proposed rules
for `ref` name encoding would be at odds with allowing this code to be valid C#; while that particular scenario would be okay
because the constraints would force the creation of two different skeleton containers, the constraints are not the important bit
that allows the code to be valid. What allows the code to be valid is the `ref`ness, and it would be odd to have a form that is
allowed in C# but we can't actually emit in many cases. Given this, the working group will take another look at the conflict rules
and bring back a new proposal for how to encode these bits.

#### Extern support

Question: https://github.com/dotnet/csharplang/blob/d9aac41d8b0ff4d2bb322ffb8f85a4a4a14690df/proposals/extensions.md#extern

We confirmed support here. Existing extensions support `extern`, so the new ones will too.

#### Lookup

Question: https://github.com/dotnet/csharplang/blob/d9aac41d8b0ff4d2bb322ffb8f85a4a4a14690df/proposals/extensions.md#lookup

##### Question 1

> Confirm that we want betterness rules to apply even when the receiver is a type

Next, we looked at the proposed static member betterness rules. The existing rules are based on the model that there is an implicit
parameter here, the type itself, and that therefore everything that goes into standard parameter checking should go into
betterness for static invocations. We don't feel that this is a convincing argument, as there is no value to applying refness to here.
Further, it would mean that users would need to understand that it would be a source-breaking change to move an extension from an
`extension(in int)` block to an `extension(int)` block, because it could affect the tiebreaking with another library's extensions.
We therefore conclude that static extension lookup will only look at the type being extended when doing resolution, not any other
tiebreaking criteria.

###### Conclusion

For static extension members, we will only use the type for the extra "parameter".

##### Question 2

> Confirm that we don't want some betterness across all members before we determine the winning member kind

We're concerned here that if we don't support some form of betterness, it will block users from being able to move things that are
currently written as extension methods but would be better written as extension properties. These APIs are expressed as well as
they can be today, given that we don't have extension properties today. We feel strongly that these APIs should be able to work,
but we are also uncertain as to whether we can reasonably deliver this experience before C# 14 releases. The status quo does
protect our ability to design rules that by and large do the "right" thing by default, invoking methods where appropriate and
calling properties when appropriate. We'll therefore proceed with this, and work on a design for making this "just work".

###### Conclusion

Ambiguity rules will be left in place while we work on creating rules for making code work as the user would expect.
