为什么 C# 允许我将默认接口实现声明为 "sealed",但当我这样做时却表现不一致?

Why does C# allow me to declare a default interface implementation as "sealed", but then behave inconsistently when I do?

新的 C# .NET Core 控制台应用程序:

using System;

namespace Interface_Sealed
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(new C().X);
            Console.WriteLine((new C() as I).X);
            Console.ReadKey();
        }

        interface I
        {
            sealed int X => 0;
        }

        class C: I
        {
            public int X => 1;
        }
    }
}

当 运行 时,这会将“10”打印到控制台。第一个“.X”是调用class C中X的实现,第二个是调用接口I上的默认实现。

为什么 C# 允许我将 X 的默认实现声明为 "sealed",然后允许我用不同的实现覆盖它而不抱怨?为什么我通过类型 I 或类型 C 的引用访问 X 会有所不同?

注意。如果您在 C 中显式而不是隐式地实现 I.X,您将得到 CS0539“在可实现的接口成员中找不到显式接口声明中的 'Program.C.X'”。 The Microsoft documentation page for this error 表示它发生在 "an attempt [is] made to explicitly declare an interface member that does not exist" 时。好吧,那不是真的,是吗?它确实存在。

Why does C# allow me to declare the default implementation of X as "sealed", then allow me to override it with a different implementation without complaining?

没有。您没有覆盖该成员,只是创建了一个同名的新成员。当类型是接口类型时, returns 1 未被调用的成员 的事实证明了这一点。这与从另一个继承的 classes 中的密封成员完全一致。您并没有阻止实现接口的 class 拥有它自己的具有该名称和签名的成员,您只是阻止它成为与接口(或基础 class)关联的成员。

Why does it make a difference whether I access X through a reference of type I or of type C?

因为 IC 都有 两个不同的成员 恰好具有相同的名称和签名,但行为不同。如果您能够覆盖接口的成员,它们只会有相同的行为,从而在通过接口调用时改变成员的行为。

Well, that's not true, is it?

不,这是真的。该成员不是可以实现的成员,因为它是密封的。该成员在那里,但您无法更改它的实现,因此出现错误。