Skip to content

Latest commit

 

History

History
77 lines (57 loc) · 3.97 KB

LDM-2023-07-24.md

File metadata and controls

77 lines (57 loc) · 3.97 KB

C# Language Design Meeting for July 24th, 2023

Agenda

Quote of the Day

  • "This conversation feels like it's gotten a little too much information"

Discussion

Method group natural types with extension members

#7364

First up today, we looked at a potential source of confusion that was brought up during the prototyping of extensions. Our current rule was created to protect against a potential breaking change in this scenario:

var c = new C();
var d = new D();
d.Del(c.M); // Today, this calles DExt.Del. With the change, it would call D.Del

public class C
{
    public void M() { }
}

public static class CExt
{
    public static void M(this C c, object o) {}
}

public class D
{
    public void Del(Delegate d) {}
}

public static class DExt
{
    public static void Del(this D d, Action<object> action) {}
}

However, this seems like an unlikely scenario, and it's inconsistent with how extensions behave in this same scenario when all the signatures line up. It is also in conflict with general extension lookup, which goes scope by scope. We are generally in favor of making this change, though we do need to validate that it is not breaking to ASP.NET scenarios. The other remaining question is whether we can make this change retroactively, or if it needs to be a full language change in C# 13. We do have some precedence for making "spec bugfixes" after the initial release of the feature, but those are nearly always done within months of the initial release of a feature; we're over a year and a half past the release of C# 10 at this point, and there are very realistic scenarios where developers could have VS 17.8/9 on their local machines, observing one behavior, and then have the .NET 6 SDK in CI, where a different behavior would be observed. We therefore don't think we can make this change as a bugfix, and that it will need to be a gated change in C# 13.

Conclusion

Change is approved for C# 13.

Interceptors

#7009
#7373

Continuing our review of interceptors, we looked at where experimental feature is being depended on in .NET 8. ASP.NET is planning on shipping it as part of their AOT scenario work, and has committed to doing the servicing work in the .NET 8 SDK to make sure that they adapt to any potential breaking changes that the compiler may introduce in the feature, up to and including falling back to extension method overload resolution tricks if the feature is pulled entirely. Such tricks do have cost, particularly in startup time of ASP.NET apps; given that AOT and startup time will continue to be a big focus of .NET, this would be an option of last resort.

Previous LDM meetings suggested that we wanted to look at interceptors as a compiler feature, rather than a language feature. Unfortunately, the general space is basically impossible to make such a distinction with. It still needs to have tooling support at some point, is still C# specific, and is basically hijacking overload resolution. This approach is necessitated for all the reflection-based scenarios that use information that exists outside the type system to affect runtime code; because these scenarios use information not statically available during compilation, it is hard to make them AOT-compatible. To address this, we think that we need to take another look at the scenarios that are considering interceptors and see if we can put that information back into the type system: are there features like string value types that we could leverage to avoid needing these type-system adjacent features? We will be forming a working group to drill down to the specific cases looking at interceptors, dive more deeply into what exactly they need, and what we can do to address them within the language.