[Proposal]: Non-boxing default-interface methods
Proposal champion
# Non-boxing default-interface methods
* Specification: Link to a filled out [proposal template](../../proposals/proposal-template.md). If not yet available, link to the PR adding the specification.
* Discussion: https://github.com/dotnet/csharplang/discussions/9970
## Summary
When we added default interface methods we decided that the type of `this` is the interface method itself. For classes this is not a big deal. For structs, however, it implies boxing. This has implications not just for performance, but also semantics (side-effects). It would be great if we had a way to use the type of a generic parameter constrained to the interface rather than the interface itself.
There is already a potential encoding for this in the runtime type system:
```C#
public class C {
public static void Main() {
var s = new S(1);
Console.WriteLine(s.M());
}
}
interface IFace<TSelf> where TSelf : IFace<TSelf>
{
static virtual int M(ref TSelf @this) => 0;
}
struct S(int x) : IFace<S>
{
private readonly int _x = x;
static int IFace<S>.M(ref S @this) => @this._x;
}
static class IFaceExt
{
extension<T>(ref T @this) where T : struct, IFace<T>
{
public int M() => T.M(ref @this);
}
}
```
Obviously this is a large amount of boilerplate. It would be nice for C# to help here. A simple proposal for syntax would be:
```C#
interface IFace<TSelf> where TSelf : IFace<TSelf>
{
static this int M(ref TSelf @this) => 0;
}
```
Note the `this` in the modifier section. It would take the place of the virtual/abstract modifiers as those would no longer be necessary and could be inferred based on whether the member has a declared body.
## Design meetings
<!-- Link to design notes that affect this proposal, and describe in one sentence for each what changes they led to. -->
0 条评论