Why are my C# default interface implementations not being recognized in the concrete class definition?

Viewed 433

I have a .Net 6.0 application in Visual Studio 2019. I'm trying to get default interface implementations working. For some reason, it doesn't seem to be recognizing the default implementations in the class definition.

Here is a sample code snippet:

public interface IFooBar
{
    protected bool BoolProperty { get; set; }
    protected Guid StringProperty { get; set; }
    
    protected void SampleMethod1(string param)
    {
    }
    
    protected void SampleMethod2()
    {
    }
}

public class FooBase
{
}

public class Foo : FooBase, IFooBar
{

    protected bool IFooBar.BoolProperty { get; set; }
    protected Guid IFooBar.StringProperty { get; set; }
    
    protected SomeMethod()
    {
        SampleMethod1("Test String");
    }
}

Here is a snippet from my Visual Studio 2019 project file:

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <LangVersion>preview</LangVersion>
</PropertyGroup>

Here is the error message I'm seeing.

Error CS0103 The name 'SampleMethod1' does not exist in the current context

I've got two questions/issues:

  1. Why did the compiler require me to define my interface properties as such in my concrete class: protected bool IFooBar.BoolProperty { get; set; } protected Guid IFooBar.StringProperty { get; set; }

  2. Why is the default method implementation not recognized in my concrete class?

1 Answers

It turns out that protected Default Interface Method members must be implemented explicitly by the implementing class, but can only be accessed from derived interfaces.

For example:

public interface IBase
{
    protected string StringProperty { get; set; }
    
    protected void BaseMethod(string param) => Console.WriteLine($"IBase.BaseMethod: {param}");
}

public interface IDerived : IBase
{
    public void DerivedMethod()
    {
        // SampleMethod1, SampleMethod2 and StringProperty are accessible.
        BaseMethod(StringProperty);
    }
}

public class Foo : IDerived
{
    // Protected DIM properties must be explicitly implemented.
    // They can be initialized, interestingly, but are otherwise inaccessible to Foo.
    string IBase.StringProperty { get; set; } = "StringProperty";
    
    public void Test()
    {
        // Public DIM members are available via cast
        ((IDerived)this).DerivedMethod();
    }

    // Protected DIM members can be overridden.
    // There doesn't seem to be a way to access the base method in the override.
    void IBase.BaseMethod(string param) => Console.WriteLine($"Foo.BaseMethod: {param}");
}

SharpLab.

Related