Back to Csharplang

C# Language Design Meeting for April 23rd, 2025

meetings/2025/LDM-2025-04-23.md

latest5.2 KB
Original Source

C# Language Design Meeting for April 23rd, 2025

Agenda

Quote of the Day

  • "This is worse, that's lambda calculus" "Is [redacted] in the meeting yet? Maybe they can explain it to us" "Not in one minute they can't"

Discussion

Extensions

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

Extension operators

Proposal: https://github.com/dotnet/csharplang/blob/feb7a075739e81393def6c28ab12eb7b8fdc3bb6/meetings/working-groups/extensions/extension-operators.md

We started today by looking through the latest proposal on how we want to work with extension operators. We like the proposal in general, and spent time talking about the open question: whether to put restrictions on scenarios where the operator could potentially "lose" to a built-in conversion. For example, if an extension operator + is on a type parameter T, then when int is substituted for T, that operator could potentially silently lose to a language-default operator. While this is true, we don't think we need to try and come up with a set of rules to protect users from this possibility; if it happens, it happens. Unlike other types of restricted operators, there's no potential for the "wrong" thing to happen, where a built-in operator would be overridden by an extension operator. Given this, we're happy with the proposal, and will not put restrictions on type parameter extensions.

Conclusion

Approved. We will not restrict extensions on type parameters with more rules about what operators are valid.

Overload resolution priority

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

Next, we looked at a brief question on whether OverloadResolutionPriorityAttribute should apply to properties in extensions. This scenario can occur when a single static class contains more than one extension block, which define an overloaded set of properties. In such a scenario, authors might want to use something like ORPA to avoid ambiguity errors for their users. We think this is a good idea; there might be some discoverability issues with this solution, given that ORPA can usually only be used on indexers, but ORPA itself is generally pretty niche and not well-known anyways. It's intended as an uncommon, last-ditch tool, not a generalized solution for any lookup problem. The main question is timing: we don't think this is critical for v1 of extensions, so if it has to slip to the next version of C# to get more important bits of extensions out the door, so be it.

Conclusion

We will allow ORPA to be used on extension properties, and the containing type of the extension property is the static class that contains the extension block.

Dictionary Expressions

Champion issue: https://github.com/dotnet/csharplang/issues/8659
Specification: https://github.com/dotnet/csharplang/blob/feb7a075739e81393def6c28ab12eb7b8fdc3bb6/proposals/dictionary-expressions.md#question-special-case-comparer-support-for-dictionaries-and-regular-collections

We previously talked about what collection expression arguments should do on interface types, and as part of that discussion, wanted to explore a more specialized syntax for just providing comparers. This syntax would potentially entirely replace the generalized collection expression argument feature, so the working group went off and explored the idea. After looking at the results, we don't think a specialized syntax for just comparers is the right approach. Even within the BCL, there's potential for more than just capacity and comparer arguments. ImmutableDictionary, for example, has both keyComparer and valueComparer parameters. We also don't want to invent 2 ways to specify parameters for dictionaries, one that needs to be used when the target type is an interface, and one for when the target type is any other concrete type. Given that, we want to proceed with the full collection expression arguments feature, even for interfaces. Our main question at this point is whether to use a curated list of constructors for the dictionary interfaces, or let the full set of constructors of the underlying type show through. For IDictionary, it seems like it might be ok; after all, we guarantee what the concrete type used to create one is. However, for IReadOnlyDictionary, we do not guarantee this, we only say that a compatible implementation must be used. Therefore, for now, we will curate the constructors to just the ones that take a comparer, capacity, or both, and no others. We can expand in the future if there are motivating scenarios, rather than being very lax now and potentially regretting our inability to change later.

Conclusion

Specialized comparer-only syntax is abandoned. We will move forward with collection expression arguments for interface types, using a curated set of constructors that take either a comparer, capacity, or both.