# C# Language Design Meeting for March 24th, 2025

## Agenda

- [Dictionary Expressions](#dictionary-expressions)
    - [Support dictionary types as `params` type](#support-dictionary-types-as-params-type)
    - [Type inference for `KeyValuePair<K, V>` collections](#type-inference-for-keyvaluepairk-v-collections)
    - [Overload resolution for `KeyValuePair<K, V>` collections](#overload-resolution-for-keyvaluepairk-v-collections)
- [Extensions](#extensions)
    - [Signature conflict rules](#signature-conflict-rules)
    - [`extension` vs `extensions`](#extension-vs-extensions)

## Quote(s) of the Day

- "A syntax question with no hands? That's impossible" ... "I'm going to mis-spell whichever one we choose anyways"
- "What is snoisnestringsxEg?" "Something happened in liveshare" "Oh, that's not the syntax suggestion?"

## Discussion

### Dictionary Expressions

Champion issue: https://github.com/dotnet/csharplang/issues/8659  
Specification: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/dictionary-expressions.md

#### Support dictionary types as `params` type

Question: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/dictionary-expressions.md#support-dictionary-types-as-params-type

Our first topic today is about whether we should support `params` parameters of dictionary types. This is really a breaking change, as it means that we would potentially use
an indexer for a dictionary-like type, where we currently use an `Add` method. That would likely result in a change from throwing semantics to overwrite semantics, so anyone
depending on potential exception behavior will see a behavioral difference. However, that's nothing specific to `params`, as the same is true for any other collection expression
targeted to a dictionary-like type, so we're not concerned about the potential for breaks in this specific corner.

We like this change overall, as it keeps the language simpler, even if the compiler is more complex. The goal we had with expanding `params` was that anything you could use a
collection expression for, you could `params`. Rather than re-adding the decoder ring of "what can be `params`'d vs collection expression'ed", we keep the correspondence simple,
though at the expense of more compiler developer work.

##### Conclusion

We will allow use of `params` on dictionary-like types that can be targeted with a collection expression, and constructing those types will prefer using indexers when available,
just like when using a collection expression to create that same type.

#### Type inference for `KeyValuePair<K, V>` collections

Question: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/dictionary-expressions.md#type-inference-for-keyvaluepairk-v-collections

We like these proposed rules, as they honor the goal of making KVP as transparent as tuples for these types of targets. There is a minor breaking change here as well, in that
type inference can now succeed where it previously failed, meaning that overload resolution may find a nearer applicable method (for example, not going out to extensions
because there's now an applicable instance method). We're ok with this type of break, so we'll accept these rules as written.

##### Conclusion

Rules accepted as written.

#### Overload resolution for `KeyValuePair<K, V>` collections

Question: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/dictionary-expressions.md#overload-resolution-for-keyvaluepairk-v-collections

Again, we like the analogy with tuple behavior that is happening here. If we ever run into a scenario where these rules behave differently than tuples would in this same
area, we should bring that back for discussion. Otherwise, this is approved.

##### Conclusion

Rules are accepted as written

### Extensions

Champion issue: https://github.com/dotnet/csharplang/issues/8697  
Specification: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/extensions.md

#### Signature conflict rules

Question: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/extensions.md#extension-declaration-validation  
> The current conflict rules are:
>  1. check no conflict within similar extensions using class/struct rules,
>  2. check no conflict between implementation methods across various extensions declarations.
>
> Do we stil need the first part of the rules?

First up in extensions, we looked at whether we still need/want both parts of the extension validation rules. The 2 rules serve different purposes. The second rule covers our
ability to actually emit method signatures; this is the rule that prevents two extension blocks on different types from having the same static method. The first rule is more
about preserving class experience; this is the rule that prevents having a static and instance method with the same name and parameters on the same type. We're hesitant to
remove this rule without further examples of where it would be useful, and more exploration of where it would be problematic. This rule also protects things like being unable
to declare both `int Prop { get; }` and `void set_P(int i) { }` in the same type, and is intended to help prevent concerning consumption scenarios. For example:

```cs
class C
{
    static Color Color { get; }

    static void Main()
    {
        Color.M(); // What M is called?
    }
}

class Color
{
    public static void M() {}
    public void M() {}
}
```

We don't want to mess with validation of so-called `Color`/`Color` scenarios now, so absent further evidence, we will keep the rules as is.

##### Conclusion

Both rules are retained.

#### `extension` vs `extensions`

Question: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/extensions.md#open-issues

Finally today, we have a syntax bikeshed; do we prefer `extension` or `extensions` as the keyword? After some debate, we boiled this down to whether we think of the entire block
as a true group of items or not. Or, in other words, can we think of moving the parameter down to the individual methods involved and have everything still be exactly the same?
We have repeatedly concluded that yes, we do not think of the block as a construct with true meaning; writing out 10 extension blocks on the same underlying type, or grouping
them together into a single block, has the same meaning. Therefore, we will continue with the name `extension`.

We also had a small discussion on what to name the grouping of extension methods itself; we'd like to have a consistent name to use in documentation, in compiler API names, etc.
We spitballed a number of options:

* extension declaration
* extension block
* extension body
* extensions
* extension group
* extension container

Only "extension group" and "extension block" attracted any support, and of them "extension block" was heavily preferred, and not disliked by anyone. Therefore, we will call this
grouping an "extension block".

##### Conclusion

The keyword is `extension`, and the term for the entire set of extension methods is an "extension block".
