在C#中写"private"关键字有什么原因吗?

128
据我所知,在C#中,private是默认的修饰符,无论在哪里(这意味着如果我不写publicprotectedinternal等关键字,它将默认为private)。(如果我错了,请纠正我。)
那么,为什么要写这个关键字,或者为什么成员需要这个关键字呢?
例如,当事件处理程序自动生成时,它看起来像这样:
private void RatTrap_MouseEnter(object sender, CheeseEventArgs e)
{

}

为什么它甚至会写private,如果那是暗示和默认的呢?只是为了让新手开发者(不知道这是C#的默认设置)知道它是私有的吗?还是编译器有区别?

此外,在仅写“private”(独自一行)的情况下,是否存在改变成员可访问性的案例?


19
据我所知,“顶层”类型默认情况下将是“internal”,但这个说法需要进一步确认。 - Jeff Mercado
5
所有内容的默认值都不是私密的,正如所指出的那样,通常最好明确声明。 - James Michael Hare
1
相关:C#需要私有关键字吗? - BoltClock
2
所有东西的默认设置都是“尽可能私有”。显然,非嵌套类不能是私有的,否则无法实例化或使用它。但成员默认为私有,嵌套类默认为私有。在C#中,所有东西默认情况下都具有最受限制的可见性级别。 - Ryan Lundy
显示剩余2条评论
10个回答

182
据我所知,在C#中,私有是默认的(这意味着如果我不写public、protected、internal等,它将默认为private)。(如果我错了,请纠正我。)但事实并非如此。在命名空间中定义的类型(类、结构体、接口等)默认为“internal”。此外,不同类型内部的成员具有不同的默认可访问性(例如接口成员的公共访问性)。有关详细信息,请参阅MSDN上的“Accessibility Levels”。
此外,
那么,为什么要写这个关键字,或者说它为什么存在?
显式指定可以帮助明确表示您将类型设置为私有。这有助于随着时间的推移保持代码的可维护性。这可以帮助其他开发人员(或您自己)知道成员是默认私有还是故意的,等等。

1
@Wayne:他的回答得分比Jon Skeet高,但他并不值得。Jon的回答更加准确。 - aleroot
4
这是一个毫无意义的区分。在命名空间内部,默认情况下,类型是内部的,因为它们默认情况下无法是私有的;否则,没有任何东西能使用它们。它们仍然按照默认设置尽可能受限。 - Ryan Lundy
1
内部类和结构的默认成员可访问性为私有。请在此处查看:http://msdn.microsoft.com/zh-cn/library/ba0a1yw2(v=vs.90).aspx - Mitja Bonca
但是命名空间内部的元素不能是“private”。 - Shimmy Weitzhandler
此外,getset默认为属性本身的可访问性。 - AustinWBryan

131
据我所知,C#中默认情况下私有是所有成员的默认访问级别。但并非完全如此——默认情况下访问级别为“该声明可用的最受限制的访问级别”。例如,在顶级类型中,默认值为internal;在嵌套类型中,默认值为private。
那么,写这个关键字的原因是什么,或者它为什么存在呢?有两个好处:
- 对于不了解默认设置的人来说,它使代码更加清晰(个人而言,我从不喜欢这个论点,但我认为值得提一下)。 - 它给人一种印象,即您已经「故意」将其设置为私有,而不是只使用默认设置。
至于你最后的问题:单独写“private”会改变成员的可访问性吗?
会,可以用来使属性的其中一部分比另一部分更受限制。
// Public getter, public setter
public int Foo { get; set; }

// Public getter, private setter
public int Bar { get; private set; }

我曾经尽可能地使用默认设置,但现在我已经被说服(至少是被 Eric Lippert 部分说服)认为表明你已经思考过并决定将某些内容设为私有是一个好习惯。

就我个人而言,我希望对于类型声明的密封/非密封也有一种类似的方式 - 也许甚至不需要一个默认设置。我怀疑许多开发人员(包括我自己,如果我不小心的话)之所以让类保持为非密封的状态,只是因为这比将它们密封起来更省事。


1
@minitech:反过来也可以,但不太有用。这些都是在C# 2中引入的。 - Jon Skeet
24
我希望完全没有默认值,如果访问修饰符缺失,编译器应该直接报错。我认为大多数人并不知道每种情况下的默认值,这会导致意外错误。 - user315772
6
对于C#,有一个简单的规则:默认情况下,所有内容都是尽可能私有的。例如命名空间中的非嵌套类不能是private,因为没有任何东西能够使用它们。它们只能是internal或public,默认情况下是internal。其他嵌套在类中的元素(如枚举、嵌套类、属性、字段、方法等)默认情况下是private的。 - Ryan Lundy
@ObsidianPhoenix:我没有看到任何这样的提示。也许你在某个地方指定了一个选项? - Jon Skeet
@ObsidianPhoenix:如果找不到选项,那就去寻找一个,并提出功能请求吧 :) - Jon Skeet
显示剩余10条评论

19

private 增加了视觉混乱。 对于那些坚持认为这会使事情更加明确的人,我想问:你在数学中也这样做吗?例如:

私有成员增加了类的复杂性,降低了代码可读性,所以不建议频繁使用。对于坚持认为使用私有成员可以使代码更加明确的人,我想问:在数学中你是否也这么做呢?例如:
var answer = a + b / c;

你觉得在b / c周围没有冗余的括号会更加不清晰吗?

C#中的规则非常简单:默认情况下,所有内容都尽可能接近于私有。因此,如果您需要使某些内容比默认可见性更高,请添加修饰符。否则,请不要在代码中添加不必要的关键字。


3
在提问之前,我曾同意这个观点。但是,有些人写VB,有些人写C++,甚至有些人用F#(来自其他函数式语言,比如Haskell?)比他们在C#上表现得更好。因此,对于他们(以及我们如果在两年没有使用C#后忘记了它),如果访问器是显式的,则更好。不要低估易学性对项目的影响,许多开发人员来自可能不反映首选工具的背景,并且他们确实需要学习辅助工具,即使在生产代码中,这并不坏(我们知道许多人编写非常糟糕的C#代码,因此一些辅助工具也对我们有所帮助)。 - Camilo Martin
4
没问题,VB的默认设置确实很糟糕。例如,成员的默认可见性是“Friend”。而C#则采用了正确的策略:除非进行更改,否则所有内容都被设置为最小可见性。从我所了解的情况来看,C++也是如此(结构体除外)。但据我所知,F#则不一定如此。 - Ryan Lundy
13
很奇怪,很多人喜欢使用 var 来减少视觉混乱,但也有很多人却喜欢毫无意义地输入 private - Ryan Lundy
5
我甚至认为视觉混乱会阻碍阅读能力! - binki
2
尽管在您的数学示例中,我更喜欢使用括号,但我已经点赞了。 - Marc.2377
显示剩余8条评论

7

可读性 - 并不是每个人都知道私有是默认行为。

意图 - 明确表明您已经特别声明了属性为私有(出于任何原因)。


6
可读性和表达意图是我想到的两个很好的原因。

同意。例如,如果您正在与其他开发人员共同开发一些代码,则将某些内容设置为私有可以帮助表明您的意图。当您在多年后重新进入代码时,这也很有帮助,因为您的IDE可以告诉您该类应该公开访问哪些方法。 - Aaron Newton

6
据我所知,在C#中,private是默认设置的。
明确声明private,意味着您知道它是私有的。不仅仅是认为它是私有的,因为据您所知,这是默认设置。这也意味着查看代码的其他人知道它是什么。
没有“我认为它是”,“我很确定它是”等说法。它就是。每个人都在同一页上。
我不是一个C#开发者。如果我必须使用未明确声明为private的代码,我可能会假设它是internal
我不喜欢隐式设置事物。当它们被明确设定时,永远不会像现在这样清晰。

听起来合理,我甚至忘记了我曾经更加熟悉的语言的基础知识。 - Camilo Martin
“我不喜欢事情被隐式设置。当它们被明确设置时,它们永远不会像现在这样清晰。”但是,在程序代码中,有像巴基斯坦一样多的暗示吗?我们是否使用高级语言、库、语法糖和理智的默认值,以便我们不必考虑和陈述所有细节呢? 在我的书中,较少的细节和代码是好的,并且胜过为了明确而明确。不编写私有的内容就像变量。 - One Man Monkey Squad

5
很多人(比如我!)经常使用几种不同的编程语言。对这些事情进行明确说明可以避免我需要记住所有我所编写的语言的神秘细节。

2
我不会说 "默认访问修饰符是 private" 是一个 古怪的细节...但我理解这个观点。前几天,我忘记了上周使用的框架(MEF)是如何工作的,遇到了麻烦。 - Camilo Martin

3

明确指定可见性的一个好处是不必考虑所在上下文环境的默认值。

另一个好处是因为FxCop提示你这样做。


+1,我刚刚注意到FxCop抱怨我在构建时删除了private修饰符。 - Camilo Martin
1
不要认为因为 FxCop 告诉你做某事就是好的。我看到很多我认为是不好的惯例(当然也有很多好的),这些惯例被工具和分析器所延续。 - MemeDeveloper

0

我喜欢明确地添加private关键字,这样我就知道它是私有的。此外,在各个地方,private并不总是默认的访问限定符。另外,在属性中使用private set可以有效地创建一个只读属性,只能由声明它的类进行设置。


0
我认为这样做是为了与类的其余范围的可读性保持一致。

5
您在想C++。在C#中,即使在结构体中,成员默认也是私有的。 - user743382
3
默认情况下,结构体不具有公共访问权限 - 参见:http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx - Reed Copsey

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