受保护的内部:
受保护和内部可访问性的联盟(这比受保护或内部限制更少单独)
CLR具有受保护和内部可访问性的交集的概念,但C#不支持此功能。
所以我的问题是:
省略此访问修饰符的含义是什么?有具体原因吗?那么为什么C#不应该支持呢?
答案 0 :(得分:7)
更新:C#7.2正在使用访问修饰符private protected
引入它,这在某些方面似乎有误,但确实避免了我在下面描述的混淆的可能性,所以也许是最糟糕的一堆
就我个人而言,我已经想过这么多次了。有时会在程序集中公开一个类以及从它派生的一个或多个类public
,并且有时基类的某些成员仅由这些派生类使用,并且不应该暴露给它们其他程序集中的受保护类(通常是构造函数,以防止其他程序集具有从中派生的类)。
当然最好尽可能限制地定义您的访问权限,因此受保护和内部的交集正是这里所需要的。
相反,我必须通过声明成员internal
来克服它。如果我使用允许我使用该交集的语言,我的代码中可能存在可能存在错误的错误。
然而,考虑下行。
实际上,protected internal
赋予protected
和internal
联合的方式存在一些混淆。这可能是最容易被误解的访问,可以通过这样的网站上的问题来判断。
我们应该怎么称呼它? internal protected
?你能想象人们会多久经常与protected internal
混淆吗?我们想要一些更明确区分的东西,我们希望internal protected
有同样的东西(因为我们仍然增加了混淆的可能性)。这不是一个不可能回答的问题,但保持关键字的数量也是一个好主意。
即使找到了命名问题的完美答案,通过引入另一个访问级别而导致混淆的可能性并未完全失败。
因此,考虑到这一点,让我们再看看好处。我们不再需要使用internal
来克服我们需要的时间,从而减少因使用这种成员而导致的错误。好的,这种情况多久发生一次,这种错误实际上有多大可能性?不是很常见,也不太可能。
因此,总的来说,虽然我发现自己偶尔希望C#有这个,但片刻暂停通常会让我很高兴他们没有。
答案 1 :(得分:6)
protected
和internal
的交集将降级到您的库外部代码的简单internal
- 这意味着无法从派生类或其他方式访问它。
因此,protected internal intersection
所能提供的唯一好处是,作为库的开发人员,不要使用库中相同或派生类来访问类型/成员。它对你的库的消费者没有任何影响,因为它的语义与普通的internal
相同。
那就是说,我不会觉得它被允许进入C#是不合理的。自律通常很有用;这就是语言设计师区分private
和internal
的原因,尽管两者对于外部消费者来说是相同的。
但是,由于交集和普通internal
之间的区别很小,他们可能会选择将其排除,以降低开发人员将其与更有用的protected internal
联合混淆的风险。
答案 2 :(得分:3)
这是一项设计决定,但请考虑它的含义:
这不是一个非常有用的界限,我想不出一个明确的用例 这就是为什么它可能不值得提出一个新的关键字(-combination)。
我宁愿问为什么CLR支持它。我认为正交性。
答案 3 :(得分:2)
那么为什么C#不应该支持它?
错误的问题。问题应该是“为什么应该 C#支持protected and internal
?”
请注意,功能的自然状态是不实现。在资源,测试方面实现功能非常昂贵,而且不要忘记,机会成本(意味着它取代了其他功能)。因此,为了克服这些费用,最好能够实现一项能够克服这些成本的功能。
特别是protected and internal
的价值是多少?确实没有充分的理由将可访问性限制在同一程序集中的派生类。
IMO奇怪的是CLR支持它,但确实如此。这并不意味着C#需要这样做。
答案 4 :(得分:2)
我想问同样的问题,但谢天谢地,我找到了这个问题。
我可以理解,它至少需要一个新关键字或现有关键字的新语义,所以它不受支持,因为成本效益对它不利。
但是,我怀疑是否合法避免实施此CLR功能是因为用例较窄或者因为它会让人感到困惑。
上面给出的一个论点是,它的唯一用途就是强制执行自律。
但是对于任何不是public
的可见性修饰符都可以这么说。同样,它只适用于“单个图书馆的单一开发者”的想法也是明显错误的。许多库是由人员团队开发的,对于该团队中的开发人员来说,添加一个他或她想要仅限于从他或她的基础派生的内部类型的成员是完全自然的。
然后是这种情况:
internal class Foo {
}
public class PublicBase {
protected Foo MyFoo { get; set; }
}
在这种情况下,我有一个我希望在类上公开的内部类型,但我只想将它公开给派生类型。由于类型是内部的,因此隐含地表示同一程序集中的派生类型。外部类型仍然可以合法地继承此类型,但它们不需要使用此成员。
在这种情况下,我陷入困境:我无法使用protected
,也无法使用protected internal
。
相反,我必须使用internal
,它错误地向我的团队的其他成员广播它应该从课外的代码中使用它。当然我可以对它进行评论(甚至坚持EditorBrowsableAttribute
Never
,但这也会将其隐藏在内部继承者之外 - 但它不一样。
实际上,我能够实现这一目标的唯一方法是在构建之后使用IL重写来破解程序集 - 但是我需要在编译时提供这种可见性(或缺少它),而不是在构建之后。
最终,关于“它将使用什么关键字”或“如何实现”的争论与我无关:我是程序员,不是C#语言设计师。
同样地,我不得不说像这样的论点“好吧,protected internal
对许多人来说足够混乱”也无关紧要。我接触过很多开发人员,无论是亲自还是虚拟,谁不理解?:
或一般约束之类的东西 - 猜猜是什么,他们不使用它们!这并不意味着我不应该。
所以是的,我理解不实现它的原因 - 但我不同意它们 - 因此我对C#不支持它的答案是因为C#设计师弄错了。
是的,我已经准备好迎接可能带给我的热量了。)
答案 5 :(得分:0)
据我所知,您可以使用受保护和内部访问修饰符的交集,但不能使用您想要的解释(可能是因为Henk所说的):
受保护:类型或成员只能由同一类或结构中的代码或派生类访问。
内部:类型或成员可以由同一程序集中的任何代码访问,但不能从其他程序集访问。
受保护的内部:类型或成员可以由同一程序集中的任何代码访问,也可以由另一个程序集中的任何派生类访问。
答案 6 :(得分:0)
你总是可以这样做:
public MyExternallySealedClass
{
internal MyExternallySealedClass() {...}
...
}
只要您不让任何外部消费者实例化该对象,如果他们尝试推导它,您会关注什么?简短的回答,您要求的功能不会带来任何新功能,您已经拥有了执行所请求工具的工具。