为什么不能隐式实现非公共接口成员?

Eug*_*mov 0 c# access-modifiers c#-8.0

界面:

interface IMyInterface{
  internal int Property {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

班级:

public class MyClass: IMyInterface{
  internal int Property {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

结果: CS8704 错误:MyClass 未实现接口成员 Property.get MyClass 无法隐式实现非公共成员。

为什么我必须显式实现接口?

Joe*_*ell 5

“为什么是这样的语言”的简单答案是“因为这就是语言设计者指定它的方式”。

那么,他们为什么要这样设计呢?我找到的一些官方注释是这些。看来主要问题是实施者必须拥有什么样的访问权限:

我们是否允许隐式实现非公共接口成员?如果可以,那么实现方法的可访问性要求是什么?一些选项:

  • 必须是公开的
  • 必须具有完全相同的可访问性
  • 必须至少是可访问的

他们决定:

现在,我们只是不允许这样做。只有公共接口成员可以隐式实现(并且只能由公共成员隐式实现)。

“现在”从未改变,因此从 C# 8 开始,接口可以具有非公共虚拟成员,但类只能显式实现它们。

我可以推测他们可能决定反对这样的隐式覆盖的几个原因:

  • 接口中的非公共虚拟方法可能被认为是一种“罕见”功能(毕竟,接口不是应该记录类的公共行为吗?),不值得在语义方面投入大量资源。隐式覆盖。
  • 与类到类继承中的方法重写不同,实现接口方法的类方法不使用关键字override。看到受保护和/或内部方法但没有意识到它正在履行接口契约可能会被认为是令人困惑的。(公共方法大概被认为可以免除这个问题,因为这就是它们一直工作的方式,并且公共方法无论如何都是类公共契约的一部分,因此修改/删除它们已经会导致读者考虑代码的其他部分这取决于它。)
  • 接口只能显式地重写其他接口方法,这可能又是因为允许接口到接口的隐式实现对于编译器和工具团队来说成本太高,并且对于 C# 用户来说太混乱。(特别是因为接口到接口的继承是多重继承。)由于此方法和非公共接口方法通常都是在 C# 8 中引入的,因此使这两个功能在语法上匹配可能是有意义的。

另请参阅默认接口方法提案中关于此问题的注释