meetings/2025/LDM-2025-03-24.md
Champion issue: https://github.com/dotnet/csharplang/issues/8659
Specification: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/dictionary-expressions.md
params typeOur 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.
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.
KeyValuePair<K, V> collectionsWe 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.
Rules accepted as written.
KeyValuePair<K, V> collectionsAgain, 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.
Rules are accepted as written
Champion issue: https://github.com/dotnet/csharplang/issues/8697
Specification: https://github.com/dotnet/csharplang/blob/bcc689fafe8c2d226b8a3034eb7f66f48495e3aa/proposals/extensions.md
The current conflict rules are:
- check no conflict within similar extensions using class/struct rules,
- 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:
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.
Both rules are retained.
extension vs extensionsFinally 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:
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".
The keyword is extension, and the term for the entire set of extension methods is an "extension block".