计划中的“受私有保护”的C#访问修饰符是什么意思?


133

作为GitHub上Roslyn文档的一部分,有一个页面叫语言功能实施状态,其中包含计划的C#和VB语言功能。

private protected访问修饰符是我无法解决的一个功能:

private protected string GetId() {  } 

还有一个C#语言设计说明页面,其中介绍了许多新功能,但没有介绍这一功能。

埃里克·利珀特(Eric Lippert)在评论中说:

您的错误是将修饰符视为增加的限制。实际上,修饰符总是会减少限制。请记住,默认情况下事情是“私有的”。仅通过添加修饰符,您才能使它们的约束更少。

是什么意思private protected?我什么时候可以使用?


2
请注意,在VB语言设计说明下有关于它的信息。
Jesse Good

3
它是到MethodAttributes.FamANDAssem的映射。C#具有内部的奇怪映射,它使用(Private | FamANDAssem)。并且内部受保护者映射到(私人|家庭)。CLR属性很奇怪。
Hans Passant 2014年

22
建议的功能会使我的评论不正确。
埃里克·利珀特

C#设计团队发布了一项调查,其中提供了针对此功能的建议替代语法。其中有些是有趣的,像protected & internalassembly protectedproternal(我希望有这些都是玩笑)。还有一个带有一些不错见解的讨论线程
科比

1
现在,该功能在“语言功能”实施状态中标记为已撤消!我个人很喜欢这种访问级别的概念,并且我认为它是一个有用的功能。我想使用受保护的代码来根据类设计保留我的代码,但我不希望其他人编写可访问此成员的hacky sublases。IMO最好的解决办法是,如果我们可以写protected | internalprotected & internal
费利克斯·凯尔

Answers:


98

根据De Bill Evjen和Jay Glynn,第1699页的“ Professional C#2008 ”:

受私有保护-“仅当前程序集中的派生类型”

C ++ / CLI具有类似的功能- 定义和使用类和结构(C ++ / CLI)>成员可见性

private protected-或者protected private--成员在部件内部受到保护,但在部件外部受到保护。


72
因此,它的“保护内部”,而不是“保护内部的”?
user541686 2014年

2
现在可以使派生类可访问的成员接受或返回internal类型的东西,而无需将该成员本身暴露给程序集中的所有内容吗?
supercat 2014年

谢谢!我没想到。实际上,我有一些情况我本可以使用该修饰符,然后又重新使用internal
Kobi 2014年

3
这个建议/功能的存在似乎表明,internal能见度(相关类的定义在哪里)是真正正交public/ protected/ private可见性(与遗传有关),而且,也许,internal应该是自己的修改从分离public/ protected/ private
jpmc26 2014年

1
@jww-我对Java不太熟悉,但是据我所知package,Java更像C#中的命名空间。
Gogutz 2014年


28

这只是为了提供一张不同可访问性级别的图像(由http://ashitani.jp/gv/制成)(图像不适合注释)。

C#访问级别的图

每个箭头表示“比...更具限制性”。

CLR的名称PrivateFamilyANDAssemblyAssemblyFamilyFamilyORAssemblyPublic


后来的编辑:事实证明,这个不错的新访问级别(名称确实很差)最终并未包含在C#6.0中。仅C#7.2支持此功能(我看到您更新了问题“标签”)。


可能只是我,但箭头似乎朝着“限制程度小于”的方向发展。
acarlon 2014年

4
@acarlon是的,因此a → b在图中表示“ ab” 更严格,因此您可以“将”箭头读为“比”更严格(这就是我试图解释的内容),因此箭头指向的限制最小。方向”。顺便说一句,箭头的相反约定本来可以很好,但是我不得不选择一个约定。
Jeppe Stig Nielsen

10

只是一个猜测,但是从名称上您可能会猜到它是的更严格的版本protected(或者,private如果您愿意的话,可以是更宽松的版本)。并且它的唯一合理变体是将protected行为限制为组装。

可能的用法:那么您想要拥有protected内部实现,而不是拥有外部使用(并且您不想密封该类)。

PS它始终存在于CLR中,但在C#中不存在。它的组合protected internal,报价:

CLR还支持“家庭和装配体”访问类型。这意味着可以从声明类型,嵌套和派生类型内部访问该方法,但前提是必须在同一程序集中声明它们。好吧,显然C#团队并不认为这是一个非常有用的功能,因此该语言不支持该功能。


+1表示CLR注释-这些天,我在C#中花了很多时间,而在其他.NET语言中却花了很少的时间,我有时会忘记它们不是同一回事。
brichins 2014年

@DarrelHoffman感谢您的注意!我在这里有点混在一起)
Petr Abdulin


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.