为什么当两个类在继承链中并且中间的类为空时调用接口的默认实现

Vic*_*aru 14 c# interface .net-5

概括

我发现在接口和另一个派生类之间插入一个类会导致调用接口的默认实现而不是同一方法的派生实现。这是意料之外的行为。为什么会这样?

例子

我创建了一个重现问题的示例项目:

    public interface IPrinterInterface
    {
        public void PrintIt() => Console.WriteLine("Interface");
    }

    public class MiddlePrinter : IPrinterInterface{}

    public class Printer : MiddlePrinter
    {
        public void PrintIt() => Console.WriteLine("Class");
    }

    class Program
    {
        static void Main(string[] args)
        {
            var printer = (IPrinterInterface)new Printer();
            printer.PrintIt(); // This prints "Interface"
            Console.ReadLine(); // so the app sits
        }
    }
Run Code Online (Sandbox Code Playgroud)

此代码导致Interface被打印出来。

相比之下,如果从继承中移除 MiddlePrinter 类(如下面的代码所示),则代码打印“Class”:

    public interface IPrinterInterface
    {
        public void PrintIt() => Console.WriteLine("Interface");
    }

    public class Printer : IPrinterInterface
    {
        public void PrintIt() => Console.WriteLine("Class");
    }

    class Program
    {
        static void Main(string[] args)
        {
            var printer = (IPrinterInterface)new Printer();
            printer.PrintIt(); // This prints "Class"
            Console.ReadLine(); // so the app sits
        }
    }
Run Code Online (Sandbox Code Playgroud)

我没想到会看到这种行为,有人可以解释为什么会这样吗?

平台

这已在 .NET5 控制台应用程序和现代 Xamarin Android 应用程序中重现。

小智 5

类不从接口继承成员,即使是默认实现也是如此。来源

请注意,类不会从其接口继承成员;此功能不会更改

因此,由于MiddlePrinter不包含Printer要覆盖的继承成员,因此PrintIt()IPrinterInterface的角度来看,最具体的实现是它自己的默认实现。

通过尝试将override关键字应用于 ,这一点很明显Printer.PrintIt()。您将收到一个错误,指出找不到合适的方法来覆盖。

没有MiddlePrinterPrinter通过替换默认值提供更具体的实现。