为什么C#不支持Protected和Internal可访问性的交集?

内部保护:

受保护内部可访问性的结合(这比受保护或仅内部的限制更少)

CLR具有受保护内部可访问性交叉的概念,但C#不支持此function。

所以我的问题是:

省略这个访问修饰符的含义是什么,有一个具体的原因吗? 那么为什么C#不应该支持呢?

更新:C#7.2引入了这个访问修饰符private protected ,这在某些方面似乎是错误的,但确实避免了我在下面描述的混淆的可能性,所以也许是坏的最好的一堆。

就个人而言,我想要这几次。 有些时候,一个类和一个或多个派生它的类在程序集中publicpublic ,有时基类的某些成员只被这些派生类使用,而不应该暴露给其他类中的受保护类。程序集(通常是构造函数,以防止其他程序集具有从它派生的类)。

当然,最好尽可能限制地定义您的访问权限,因此受保护和内部的交集正是这里所需要的。

相反,我不得不通过宣布成员internal来克服它。 如果我使用允许我使用该交集的语言,现在我的代码中可能存在错误。

但是,考虑下行风险。

事实上,对于protected internal给予protectedinternal联合的方式存在一些混淆。 这可能是最容易被误解的访问,通过这样的网站上的问题来判断。

我们应该怎么称呼它? internal protected ? 你能想象人们会多久经常与protected internal混淆吗? 我们想要一些更明确区分的东西,我们希望internal protected (因为我们仍然增加了混淆的可能性)。 这不是一个不可能解决的问题,但保持关键字数量下降也是一个好主意。

即使找到了命名问题的完美答案,通过引入另一个访问级别而导致混淆的可能性也不会完全失败。

因此,考虑到这一点,让我们再次看看它的好处。 我们不再需要通过使用internal减少我们需要的时间,减少因不恰当地使用此类成员而导致的错误。 好的,这种情况多久发生一次,这种错误实际上有多大可能? 实际上并不常见,也不太可能。

因此,总的来说,虽然我发现自己偶尔希望C#有这个,但片刻的停顿通常会让我很高兴他们没有。

protectedinternal的交集会降级到库的外部代码的简单internal – 这意味着无法从派生类或其他方式访问它。

因此, protected internal intersection所能提供的唯一好处是,作为库的开发人员,不要访问类型/成员,而不是从库中的相同或派生类访问类型/成员。 它对你的图书馆的消费者没有任何影响,因为它的语义与普通的internal相同。

也就是说,我不会觉得它被允许进入C#是不合理的。 自律通常很有用; 这就是为什么语言设计师在privateinternal之间进行区分的原因,尽管两者对外部消费者来说是相同的。

但是,由于交集和普通internal之间的区别很小,他们可能会选择将其排除,以降低开发人员将其与更有用的protected internal联盟混淆的风险。

这是一个设计决定,但请考虑它的含义:

  • 只能访问同一程序集中的派生类。

这不是一个非常有用的边界,我想不出一个明确的用例。
这就是为什么它可能不值得提出一个新的关键字(-combination)。

我宁愿问为什么CLR支持它。 我认为正交性。

那么为什么C#不应该支持呢?

错误的问题。 问题应该是“为什么C#支持protected and internal ?”

请记住,function的自然状态是不能实现它。 在资源,测试方面实现function非常昂贵,而且不要忘记,机会成本(意味着它取代了其他function)。 因此,为了克服这些费用,最好能够实现一项能够克服这些成本的function。

特别是, protected and internal的价值是什么? 实际上没有充分的理由将可访问性限制为同一程序集中的派生类。

IMO奇怪的是CLR支持它,但确实如此。 这并不意味着C#需要。

我想问同样的问题,但谢天谢地,我找到了这个问题。

我可以理解,它至少需要一个新的关键字或现有关键字的新语义,所以它不受支持,因为成本效益不利于它。

但是,我怀疑是否合法避免实施此CLRfunction是因为用例狭窄或者因为它可能会让人感到困惑。

上面提出的一个论点是,它的唯一用途就是强制执行自律。

但是,任何非public可见性修饰语都可以这样说。 同样,它只适用于“单个图书馆的单一开发者”的想法也显然是错误的。 许多库是由人员团队开发的,对于该团队中的开发人员来说,添加一个他或她想要仅限于从他或她的基础派生的内部类型的成员是完全自然的。

那就是这种情况:

 internal class Foo { } public class PublicBase { protected Foo MyFoo { get; set; } } 

在这种情况下,我有一个我想在类上公开的内部类型,但我只想将它暴露给派生类型。 由于类型是内部的,因此隐含地表示同一程序集中的派生类型。 外部类型仍然可以合法地从此类型inheritance,但它们不需要使用此成员。

在这种情况下,我陷入困境:我不能使用protected ,也不能使用protected internal

相反,我必须使用internal ,它错误地向我的团队的其他成员广播,它应该从类外的代码中使用。 当然我可以坚持评论它(甚至坚持使用NeverEditorBrowsableAttribute ,但这也会将其隐藏在内部inheritance者之外) – 但它不一样。

实际上,我能够实现这一目标的唯一方法是在构建之后使用IL重写来破解程序集 – 但是我需要在编译时这种可见性(或缺少它),而不是在构建之后。

最终,关于“它将使用什么关键字”或“ 如何实现 ”的论点与我无关:我是程序员,而不是C#语言设计师。

同样,我不得不说像“好吧, protected internal对许多人来说足够混乱”这样的论点也无关紧要。 我接触过很多开发人员,无论是亲自还是虚拟,他们都不理解像?:或通用约束 – 猜猜是什么,他们不使用它们! 这并不意味着我不应该。

所以是的,我理解不实现它的原因 – 但我不同意它们 – 因此我对C#不支持它的答案是因为C#设计师弄错了。

是的,我已准备好迎接可能带给我的热量:)

你可以随时做:

 public MyExternallySealedClass { internal MyExternallySealedClass() {...} ... } 

只要您不让任何外部消费者实例化该对象,如果他们尝试推导它,您会关心什么? 简短的回答,您要求的function不会带来什么新东西,您已经有了工具来完成您的要求。

据我所知,您可以使用受保护和内部访问修饰符的交集,但不能使用您想要的解释(可能是因为Henk所说的):

  1. 受保护:类型或成员只能由同一类或结构中的代码或派生类访问。

  2. 内部:类型或成员可以由同一程序集中的任何代码访问,但不能从另一个程序集访问。

  3. 受保护的内部:类型或成员可以由同一程序集中的任何代码访问,也可以由另一个程序集中的任何派生类访问。