首页 > 解决方案 > 为什么 C# 允许我将默认接口实现声明为“密封”,但当我这样做时行为不一致?

问题描述

新的 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”是调用类 C 中 X 的实现,第二个是调用接口 I 上的默认实现。

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

注意。如果您在 C 中显式而不是隐式实现 IX,则会得到 CS0539“在可实现的接口成员中找不到显式接口声明中的‘Program.CX’”。此错误的 Microsoft 文档页面指出,当“尝试 [is] 显式声明不存在的接口成员”时会发生此错误。好吧,这不是真的,是吗?它确实存在。

标签: c#interfacesealed

解决方案


为什么 C# 允许我将 X 的默认实现声明为“密封”,然后允许我用不同的实现覆盖它而不抱怨?

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

为什么我通过类型 I 或类型 C 的引用访问 X 会有所不同?

因为两者I都有C两个不同的成员,碰巧有相同的名称和签名,但行为不同。只有当您能够覆盖接口的成员时,它们才会具有相同的行为,从而在通过接口调用时更改成员的行为。

好吧,这不是真的,是吗?

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


推荐阅读