为啥 C# 禁止对接口成员进行内部访问?

Posted

技术标签:

【中文标题】为啥 C# 禁止对接口成员进行内部访问?【英文标题】:Why does C# prohibit internal access on interface members?为什么 C# 禁止对接口成员进行内部访问? 【发布时间】:2013-10-13 07:19:35 【问题描述】:

C# 故意阻止我将内部访问修饰符放在接口成员上。我敢肯定,当他们本可以允许的时候,他们必须付出额外的努力来实施这个限制。

应该有充分的理由花费这些努力 - 哪一个?

对我来说,在接口上使用内部访问修饰符以实现“从外部防止可变性”会很有用。例如。考虑以下接口:

interface IMessage

    ...
    DateTime LastSentTimestamp  get; internal set; 
    ...

在我的消息代理内部,我希望能够设置LastSentTimestamp。我的 API 的外部用户应该能够更改它。当然,我可以放弃接口并使用类,但是,这消除了接口的所有优点(例如,随时更改实现等)

Q1:我不明白他们为什么限制我。有什么特别的原因吗?

Q2:我正在为我的上述特殊情况寻找解决方法。将界面一分为二(IMessageIInternalMessage)看起来很麻烦,希望这不是我唯一的选择......

【问题讨论】:

因为他们没有实现。 是的,他们做到了。如果他们没有实现它,我可以将内部访问修饰符放在接口成员上。 (我看出来了,你在攻击我的第二​​句话,你确定吗?) 嘿,反正我猜。我的下一个猜测是因为炸玉米饼。是不是更近了? 有时 SO 成员知道有关实施决策的详细信息,并且能够在不猜测的情况下回答此类问题 ;-) 无论如何感谢您的尝试 ;-) 您究竟为什么认为这是明确阻止且易于实施的?接口是一种契约。允许修饰符将允许您执行可以简单地使用单独的内部接口并从中继承公共接口来完成的事情。您提出的语法会增加混淆恕我直言。如果将外部实现传递给内部类怎么办?您的内部类将如何区分外部与内部实现? set 在公共实现上调用时会做什么?扔? 【参考方案1】:

我猜 C# 设计者看到的冲突是,您无法在声明程序集(和朋友程序集)之外实现具有 internal 成员的接口。当然,如果外部程序集只使用接口,这样做仍然很有用。另一方面,您可以通过第二个 internal-only 接口来获得此行为:

public interface IPublic  /* all public members */ 
internal interface IPrivate : IPublic  /* additional members */ 

您自己的类实现IPrivate。外部代码只能使用IPublic

【讨论】:

外部实现甚至不知道他们必须实现的内部成员,所以我想这应该不是问题。您使用另一个仅限内部的界面的解决方案是第一个解决方法。希望不是我唯一的选择(请参阅有问题的 Q2 ;-) 类必须实现所有接口成员。这就是为什么外部代码不能从IPrivate 继承(在这种情况下)。调用缺少的接口方法会做什么?这是未定义的,因为很难为这种情况定义有用的含义。 嗯,我明白了,这是根本问题。他们可以从外部交给我不会实现该方法的实现!谢谢,这就是我一直在寻找的原因。 在继承这样的接口时,编译器会不会用 CS0060: inconsistent accessibility: base class is less accessible than derived 这样的东西来解决问题? 准确地说,CS0061:msdn.microsoft.com/en-us/library/7f82xxf1(v=vs.90).aspx【参考方案2】:

不是你的接口的成员应该有访问修饰符,而是整个接口,以便有一致的可访问性,你的类。接口仅在由类实现时使用。接口表达了必须由实现者实现的契约。如果一个类位于接口程序集之外,它将如何实现您的内部成员?因此它无法实现契约,但其中的类必须能够......这在逻辑上是不一致的。

【讨论】:

...你能看到上面的用例吗?我真的应该将接口拆分为 IMessage 接口和第二个 IInternalMessage 接口吗?这对我来说看起来不太好......所以它可能更漂亮,但他们阻止了它 - 为什么?

以上是关于为啥 C# 禁止对接口成员进行内部访问?的主要内容,如果未能解决你的问题,请参考以下文章

为啥Java禁止继承内部接口?

F# 类将接口实现为私有成员,为啥?

C# 接口应用及意义

为啥继承具有名称签名的接口成员的 C# 抽象类至少需要实现其中一个?

C#接口

C#中接口成员的访问修饰符