# C# Language Design Meeting for July 24th, 2023

## Agenda

- [Method group natural types with extension members](#method-group-natural-types-with-extension-members)
- [Interceptors](#interceptors)

## Quote of the Day

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

## Discussion

### Method group natural types with extension members

https://github.com/dotnet/csharplang/issues/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:

```cs
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

https://github.com/dotnet/csharplang/issues/7009  
https://github.com/dotnet/csharplang/discussions/7373

[Continuing](LDM-2023-07-12.md#interceptors) 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.
