Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C# 13 ref struct interfaces - explicit interface members #44003

Open
tmds opened this issue Dec 18, 2024 · 2 comments
Open

C# 13 ref struct interfaces - explicit interface members #44003

tmds opened this issue Dec 18, 2024 · 2 comments
Assignees
Labels
doc-bug Problem with the content; needs to be fixed [org][type][category] dotnet-csharp/svc okr-quality Content-quality KR: Concerns article defects (bugs), freshness, or build warnings. Pri1 High priority, do before Pri2 and Pri3 whats-new/subsvc

Comments

@tmds
Copy link
Member

tmds commented Dec 18, 2024

Describe the issue or suggestion

The documentation on ref struct interfaces here: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#ref-struct-interfaces is stating:

From that rule, ref struct types can't declare methods that explicitly implement an interface method.

What does this mean?

I thought it meant the following would be disallowed, but it works fine.

MyRefStruct s = default;
CallFoo(s);

void CallFoo<T>(T instance) where T : IA, IB, allows ref struct
{
    CallFooForIA(instance);
    CallFooForIB(instance);
}

void CallFooForIA<T>(T instance) where T : IA, allows ref struct
    => instance.Foo();

void CallFooForIB<T>(T instance) where T : IB, allows ref struct
    => instance.Foo();

interface IA
{
    void Foo() { }
}

interface IB
{
    void Foo() { }
}

ref struct MyRefStruct : IA, IB
{
    void IA.Foo() { Console.WriteLine("IA.Foo"); }
    void IB.Foo() { Console.WriteLine("IB.Foo"); }
}

cc @BillWagner

@dotnetrepoman dotnetrepoman bot added the ⌚ Not Triaged Not triaged label Dec 18, 2024
@BillWagner
Copy link
Member

Great catch @tmds

Your example points to a subtlety in the restriction on explicit interface implementation and ref struct: The only way to call that method is through a generic method that has the allow ref struct anti-constraint.

See this sharplab for a slight addition to your sample:

using System;

MyRefStruct s = default;
CallFoo(s);
DirectCallFooIA(s); // error CS1503: cannot convert from `MyRefStruct` to `IA`

void CallFoo<T>(T instance) where T : IA, IB, allows ref struct
{
    CallFooForIA(instance);
    CallFooForIB(instance);
}

void DirectCallFooIA(IA instance) => instance.Foo();

void CallFooForIA<T>(T instance) where T : IA, allows ref struct
    => instance.Foo();

void CallFooForIB<T>(T instance) where T : IB, allows ref struct
    => instance.Foo();

interface IA
{
    void Foo() { }
}

interface IB
{
    void Foo() { }
}

ref struct MyRefStruct : IA, IB
{
    void IA.Foo() { Console.WriteLine("IA.Foo"); }
    void IB.Foo() { Console.WriteLine("IB.Foo"); }
}

This text should clarify that restriction. In addition, the text on the ref struct language reference should be augmented with this information.

@BillWagner BillWagner self-assigned this Dec 18, 2024
@BillWagner BillWagner added doc-bug Problem with the content; needs to be fixed [org][type][category] and removed ⌚ Not Triaged Not triaged labels Dec 18, 2024
@dotnetrepoman dotnetrepoman bot added ⌚ Not Triaged Not triaged labels Dec 18, 2024
@BillWagner BillWagner added Pri1 High priority, do before Pri2 and Pri3 and removed Pri3 ⌚ Not Triaged Not triaged labels Dec 18, 2024
@dotnetrepoman dotnetrepoman bot added ⌚ Not Triaged Not triaged 🗺️ mapQUEST Only used as a way to mark an issue as updated for quest. RepoMan should instantly remove it. and removed 🗺️ mapQUEST Only used as a way to mark an issue as updated for quest. RepoMan should instantly remove it. labels Dec 18, 2024
@BillWagner BillWagner removed the ⌚ Not Triaged Not triaged label Dec 18, 2024
@dotnetrepoman dotnetrepoman bot added the ⌚ Not Triaged Not triaged label Dec 18, 2024
@BillWagner
Copy link
Member

BillWagner commented Dec 18, 2024

The compiler can generate code to call a Dispose method that is explicitly implemented as well. See sharplab

using System;

using var s = new S();

s.M();

public ref struct S : IDisposable 
{
    public void M() {}
    void IDisposable.Dispose() {
    }
}

@dotnet-policy-service dotnet-policy-service bot added the okr-quality Content-quality KR: Concerns article defects (bugs), freshness, or build warnings. label Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-bug Problem with the content; needs to be fixed [org][type][category] dotnet-csharp/svc okr-quality Content-quality KR: Concerns article defects (bugs), freshness, or build warnings. Pri1 High priority, do before Pri2 and Pri3 whats-new/subsvc
Projects
Development

No branches or pull requests

2 participants