计划中的"C#私有受保护"访问修饰符的含义是什么?

136
作为 GitHub 上 Roslyn 文档的一部分,有一个名为语言特性实现状态的页面,其中列出了 C# 和 VB 的计划语言特性。
其中一个让我感到困惑的特性是private protected 访问修饰符。
private protected string GetId() { … } 

还有一个页面是C#语言设计笔记,其中解释了许多新特性,但不包括这个。

Eric Lippert在评论中说:

你的错误在于认为修饰符会增加限制。事实上,修饰符总是减少限制。请记住,默认情况下,所有东西都是“private”的;只有添加修饰符才能使它们受到更少的限制。

private protected是什么意思?我什么时候会用到它?


2
请注意,在VB语言设计说明下有相关信息。 - Jesse Good
3
这是将其映射到MethodAttributes.FamANDAssem。C#对internal有一个奇怪的映射,它使用(Private|FamANDAssem)。而internal protected则映射到(Private|Family)。CLR属性很奇怪。 - Hans Passant
22
这个提议的功能会使我的评论不正确。 - Eric Lippert
C# 设计团队已经发布了一份调查报告,提出了该功能的替代语法。其中一些很有趣,比如 protected & internalassembly protected 或者 proternal(希望其中一些是玩笑)。还有一个讨论线程,提供了一些不错的见解。 - Kobi
1
该语言特性实现状态中的功能现已被标记为已撤回!个人认为这种访问级别的想法很好,而且我认为它是一个有用的功能。我想使用protected来保持我的代码符合类设计,但我不希望其他人编写hacky子类来访问这些成员。在我看来,最好的解决方案是我们可以编写protected | internalprotected & internal - Felix Keil
6个回答

195
以下是 Venn 图中的所有访问修饰符,从限制最多到最不限制的顺序:
- private:
图像描述 - private protected: - C# 7.2 中添加
图像描述 - internal:
图像描述 - protected:
图像描述 - protected internal:
图像描述 - public:
图像描述

3
源文件图片:Access Modifiers.pdn。我使用了名副其实的 Paint.Net 软件。 - Kobi
10
这些图表在我(使用C#)的整个生涯中都去哪了?它们非常棒 - 谢谢! - Jon Peterson

98

75
所以应该是“受保护内部”,而不是“受保护内部”? - user541686
2
现在是否可以拥有一个成员,该成员可被派生类访问并接受或返回“internal”类型的内容,而无需将该成员本身暴露给程序集中的所有内容? - supercat
谢谢!我没有想到那个。实际上,我有一些情况会使用那个修饰符,但最终退而使用了“internal”。 - Kobi
3
这个提议/功能的存在似乎表明,“internal”可见性(与类定义的位置有关)与“public”/“protected”/“private”可见性(与继承有关)真正是正交的,或许,“internal”应该成为一个单独的修饰符,与“public”/“protected”/“private”分开。 - jpmc26

28

这只是为了提供一个图形(使用http://ashitani.jp/gv/制作)来显示不同的可访问级别(图片无法适应评论)。

C#访问级别的有向图示意图

每个箭头表示“比...更加严格”。

CLR的名称为PrivateFamilyANDAssemblyAssemblyFamilyFamilyORAssemblyPublic


后来编辑:事实证明,这个很好的新访问级别(名字确实很糟糕)最终没有包括在C# 6.0中。它仅受到C# 7.2的支持(我看到你已经更新了你的“标签”)。


可能只是我一个人这样认为,但箭头似乎朝着“比...不受限制”的方向。 - acarlon
4
是的,图表中的a → b表示“ab更加严格限制”,因此您可以将箭头“读作”“比……更加严格限制”(这就是我试图解释的内容),所以箭头指向最不严格的“方向”。顺便说一下,箭头的相反惯例也可能同样好用,但我必须选择一种惯例。 - Jeppe Stig Nielsen

10

这只是一个猜测,但从名称上看,您可能会猜到它是protected的更受限制的版本(如果您愿意,也可以是private的更轻松版本)。唯一合理的变体是将protected行为限制为程序集。

可能的用法:当您想要在内部实现中使用protected,但不希望对外部使用开放时(而且您不想封闭类)。

P.S. 它始终存在于CLR中,但不在C#中。它是protectedinternal的组合,如下所述:

CLR还支持“Family and assembly”访问类型。这意味着该方法可以从声明类型内部,嵌套类型和派生类型访问,但仅当它们在同一程序集中声明时才能访问。显然,C#团队认为这不是一个非常有用的功能,因此不支持此语言。


+1 对于 CLR 的评论 - 我最近在 C# 上花费了很多时间,而在其他 .NET 语言上的时间却很少,以至于有时候我会忘记它们并不是同一件事情。 - brichins
@DarrelHoffman 谢谢提醒!我在这里有些混淆了思路。 - Petr Abdulin

5

"可能"只对处于相同程序集中的子类可见。这使得它比protected受到一定限制。


1

请查看规范以了解“private protected”功能:

私有保护的直观含义是“在此程序集内,由包含类派生的类型可以访问”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接