csharplang/meetings/2021/LDM-2021-04-07.md
2021-04-13 14:33:21 -07:00

6 KiB

C# Language Design Meeting for April 7th, 2021

Agenda

MVP-nominated session agenda

  1. Abstract statics methods
  2. Making other language literals easier
  3. Expression trees
  4. Metaprogramming
  5. Cost-free delegates and LINQ
  6. Readonly locals and parameters
  7. Global usings
  8. Mixed-language projects
  9. Discriminated unions

Quote of the Day

  • "Cats are the superior pet" - followed by a lot of discussion that isn't relevant, as your note taker is a cat person

Discussion

Today we held a more informal LDM session with Microsoft MVPs, where we selected an agenda from their suggestions and a brief discussion on our thoughts around the topic, as well as getting their impressions and potential concerns on the topic.

Abstract statics method

One thing we heard today was that there are definite use cases for this feature, not just in interfaces, but also in class types. This will particularly help with abstracting construction scenarios. There are also likely cases in Objective-C and Swift interop code that will be made simpler with this feature, which we hadn't yet looked at as a possible application for this. We also briefly discussed the issue of multiple inheritance with default implementations of abstract methods, but no new problems arise from abstract statics that did not already exist with default implementations of instance interface members.

Making other language literals easier

A common complaint in C# is when users need to include literals from other languages such as XML or JSON, or even C# itself (particularly evident in source generators). While we aren't looking for language-specific literal types, we are looking at a more general "raw string" proposal that will allow more customization of escapes inside the string, which will address the problems around copying and pasting text that includes quote marks in it.

Expression trees

Some questions were raised on why we haven't updated expression trees since initial release. Our concerns here are around expression tree consumers: any update we make to start including new things in the tree will likely break consumers of expression trees. This starts to get particularly gnarly when we consider libraries that users want to ship and support on older target frameworks, or when newer code wants to depend on older code that hasn't been updated for handling of new expression tree constructs. We need a good proposal around how to handle the guardrails in these tricky scenarios to move this forward, and we don't have one yet.

Metaprogramming

Questions here centered around 2 points. First was ease of use, such as being able to define a source generator in the same project that consumes it. We are currently focussed on the V2 of the source generator API, but after that is shipped we'll be turning to focus on more general ergonomics, and this will be one of the areas we'll investigate. There are some particularly hard questions around running a source generator when the project doesn't compile.

The second point is in source replacement. We are very unsure about this feature: in particular, the IDE experience isn't great. We've already received occasional bugs from users about IDE experiences with existing code-rewriting solutions such as Fody (such as debuggers appearing to misbehave), and we have additional concerns about the perf implications of such generators.

Cost-free delegates and LINQ

A number of scenarios would like lambdas to be more efficient. In particular, some applications of LINQ should be able to be cost-free, as the results are immediately used and don't need to allocate closures. However, we don't have the language facilities to do this today. If we add the ability for ref structs to implement interfaces and be used in generics, we could get this feature, but usage would be extremely unergonomic due to the inability to infer generics parameters for some of the cases involved. To really make a feature like this usable, we would also want associated/existential types to remove those uninferrable generic parameters.

Readonly locals and parameters

This has been one of the ultimate examples of bikeshedding. We have an obvious syntax in readonly, but we are concerned that the effort the user would put into putting readonly everywhere doesn't match the actual benefit they would derive from doing so. C#'s past a mutable-first language is definitely a liability with this issue.

Global usings

We revisited why we are looking at this feature as C# syntax, and not as a project file switch. There are 2 reasons for this: we think we can do a better tooling experience in source, and we think that it will compose well with using aliases to enable other much-requested features. It does make multiple-project aliases a bit more difficult, as the user will have to include the file from multiple projects, but we think it's a worthwhile tradeoff. We also looked at global usings nested inside a namespace. We're concerned about the user experience for such constructs, and that the use case isn't there currently. If we see a need for this in the future, we can look at it then.

Mixed-language projects

While this is an interesting idea, the compiler support here is somewhat scary. Additionally, VB.NET and C# have a number of very subtle differences that could very easily lead to developer confusion. Overall, we're not pursuing this area.

Discriminated unions

While we wanted to look at discriminated unions for C# 10, we don't think we're going to be able to. In particular, there are some big questions left around type inference to be solved. Option<T>.None won't be particularly ergonomic until we do so. We also took a brief survey to see what the MVPs are looking to get out of the feature:

  • Exhaustiveness in pattern matching
  • Brevity in declaration
  • Either-or parameters to methods