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

Posted

技术标签:

【中文标题】为啥不能隐式实现非公共接口成员?【英文标题】:Why cannot implicitly implement a non-public interface member?为什么不能隐式实现非公共接口成员? 【发布时间】:2021-10-06 01:56:48 【问题描述】:

界面:

interface IMyInterface
  internal int Property get; set;

类:

public class MyClass: IMyInterface
  internal int Property get; set;

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

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

【问题讨论】:

接口成员没有公共或内部等范围。你这里有一个default interface implementation。 【参考方案1】:

internal 属性强制实现是显式的,这样接口的内部成员将保持在程序集的内部。 它可以帮助您将实现保持在内部(到程序集),以便您可以在不破坏更改的情况下更新代码,例如重命名属性。

interface IMyInterface

    internal int Property  get; set; 


public class MyClass : IMyInterface

    int IMyInterface.Property  get; set; 

【讨论】:

【参考方案2】:

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

现在,他们为什么要这样设计?我发现的一些官方注释是these。似乎主要问题是关于实现者必须拥有什么样的访问权限:

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

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

他们决定:

现在,让我们根本不允许它。只有公共接口成员可以隐式实现(并且只能由公共成员实现)。

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

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

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

另请参阅notes on this question in the default interface method proposal。

【讨论】:

【参考方案3】:

接口成员没有公共或内部等范围。你这里有一个default interface implementation。

所以需要去掉界面上的作用域:

interface IMyInterface
    int Property get; set;

【讨论】:

接口成员默认是隐式公开的,但由于默认接口方法项目的变化,现在可以声明为内部的、受保护的等。 不幸的是,它看起来像接口中的内部属性声明:语法与公共属性相同,但带有访问修饰符。语言设计者至少不能允许自动实现的属性。这样就不会那么混乱了。

以上是关于为啥不能隐式实现非公共接口成员?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 PySide 会从 Signals 的类成员中隐式创建对象成员?

公共 bool 方法不能将类型“bool”隐式转换为“void”

区别 b/w 在 C# 中隐式实现成员和显式实现成员 [重复]

C#接口的隐式和显式实现之间的区别[重复]

为啥 Linq Cast<> 助手不能与隐式转换运算符一起使用?

在 C++0x 中,非静态数据成员初始化器会覆盖隐式复制构造函数吗?