类中项目的顺序:字段,属性,构造函数,方法


637

是否有关于类结构顺序的正式C#准则?

它会去吗:

  • 公共领域
  • 私人领域
  • 物产
  • 建设者
  • 方法

我很好奇,关于项目顺序是否有严格的规定?我到处都是。我想坚持一个特定的标准,所以我可以在任何地方都可以做到。

真正的问题是我的更复杂的属性最终看起来很像方法,并且它们在构造函数之前的顶部感觉不合适。

有任何提示/建议吗?


7
实际上,要回答实际问题,不,没有官方指南。StyleCop实施为在Microsoft的特定组中使用而开发的准则。这不是官方指南,甚至在Microsoft中各组之间可能也不统一。
约翰·桑德斯

2
一个简单的技巧是查看.net中某些复杂类的元数据(VS中为F12)。您将知道至少对于publicprotected成员如何订购。
2013年

19
这个问题不是基于观点的,因为它询问是否有官方指南。有一个准则或没有准则!
SimonMᶜKenzie2014年

2
@nawfal我意识到这是一个旧评论,我喜欢您提到的技巧,但是值得一提的是它不会显示private或显示为internal成员(我相信)。观看public和的好方法protected,但是。我们可以看到.NET Framework类的源头,这里referencesource.microsoft.com
亚当Plocher

Answers:


949

根据StyleCop规则文档,顺序如下。

在类,结构或接口中:(SA1201和SA1203)

  • 常数场
  • 领域
  • 建设者
  • 终结器(析构函数)
  • 代表们
  • 大事记
  • 枚举
  • 接口(接口实现
  • 物产
  • 索引器
  • 方法
  • 结构
  • 班级

在以下每个组中,按访问顺序排序:(SA1202)

  • 上市
  • 内部
  • 受保护的内部
  • 受保护的
  • 私人的

在每个访问组中,先按静态,然后按非静态顺序排序:(SA1204)

  • 静态的
  • 非静态

在每个静态/非静态字段组中,按只读顺序排序,然后按非只读顺序排序:(SA1214和SA1215)

  • 只读
  • 非只读

展开的列表长130行,因此在这里我不会展开。展开的方法部分是:

  • 公共静态方法
  • 公开方法
  • 内部静态方法
  • 内部方法
  • 受保护的内部静态方法
  • 受保护的内部方法
  • 受保护的静态方法
  • 受保护的方法
  • 私有静态方法
  • 私人方法

文档指出,如果规定的顺序不合适(例如,正在实现多个接口,并且应该将接口方法和属性分组在一起),则可以使用部分类将相关的方法和属性分组在一起。


31
感谢您在这篇文章中所做的努力。我正在尝试使StyleCop成为标准(即使只是为了保持一致并使其易于查找)也很有价值。
肯尼·曼恩,2009年

47
我个人认为静态方法的排序很烦人。我可以看到有关静态公共方法的争论首先出现,但是我通常希望在成员之后有私有静态方法。毕竟它们是实用程序。
乔纳森·赖特2009年

18
我喜欢部分课程的小费
Keith Sirmons 2012年

10
只是关于部分类的注释。鉴于在编译时所有的部分都被编译成一个单一的类型,我将始终尝试确保创建额外开销的充分理由。局部类的主要原因是扩展自动生成的源代码或在大型项目上工作时,允许多个开发人员在同一个类上工作但使用单独的文件。
2012年

4
@FrançoisWahl与编译器相关的开销会将部分类组合成一个大的单个类型吗?
dav_i 2012年

38

与其按可见性或按项目类型(字段,属性,方法等)分组,不如按功能分组?


3
如果使用StyleCop建议“排序”,则它是一种功能。有充分的理由说明某些方法是公开的而其他方法是私有的。该代码的可读性更好:如果打开一个类的.cs文件,我会立即看到比私有方法“更重要”的公共方法(对于使用该类的人而言)
hfrmobile 2012年

75
如果您的类中有太多的方法,属性等,需要按节对它们进行分组,也许这表明该类做得太多了?
瑞安·伦迪

10
即使类很小,将公用方法与仅由该公用方法调用的相应私有方法组合在一起也有意义吗?
Markus Meyer

11
如果公共方法Foo()调用一个受保护/私有的InternalFoo(),则+1,则第二个方法最好位于源代码中的DoFoo()的正下方,而不是其他受保护/私有方法中的第二个方法。
Anders Forsgren

60
按功能分组的方法称为类
MrDosu

26

这是一个古老但仍然非常相关的问题,因此,我将添加以下内容:打开以前可能已经读过或未曾阅读过的类文件时,寻找的第一件事是什么?田野?属性?我已经从经验中意识到,几乎总是要去寻找构造函数,因为最基本的要了解的是如何构造该对象。

因此,我已经开始将构造函数放在类文件中,并且从心理上来说,结果是非常积极的。将构造函数放在一堆其他事情之后的标准建议让人感到不协调。

C#6中即将推出的主要构造函数功能提供了证据,证明构造函数的自然位置位于类的最上层-实际上,甚至在开括号之前就指定了主要构造函数。

有趣的是,这样的重新排序会带来多大的变化。它使我想起以前如何对using语句进行排序-首先使用系统名称空间。Visual Studio的“组织使用”命令使用了此顺序。现在,usings仅按字母顺序排序,而对System名称空间没有任何特殊处理。结果感觉更简单,更干净。


2
我认为类的初始化/构造是复杂的。字段在运行显式构造函数之前已初始化,因此,按照您的论点(实质上是将成员按使用/创建顺序排列),初始化字段将在显式声明的构造函数之前。初始化的静态字段和静态构造函数使其更加有趣。
David Culp

1
实际上,它们倾向于被人类寻找的顺序,即文学编程的观念,即代码应首先被人类阅读。
明亮的

1
请注意,主要构造函数已从C#6的计划中删除:stackoverflow.com/a/26915809/5085211
fuglede '16

4
在10次中有9次在寻找公共接口,这就是为什么我将所有公共成员放在首位,然后是内部成员,然后是受保护成员,最后是私有成员的原因。
马特·戴维斯

15

我不了解某种语言或行业标准,但我倾向于按以下顺序将各个部分放在#region中:

使用语句

命名空间

私人会员

公共财产

建设者

公开方法

私人方法


这正是我的做法。除了班级成员和私人成员之间,我有任何公共常数和枚举等
。– deegee

是的,我更喜欢使用私有方法保留公共财产。其他人更喜欢将构造函数放在公共属性之前...但是在我看来,我更喜欢按顺序排列值/构造函数/行为。然后将“值”划分为常量/ privateMembers /属性,依此类推。通常,我不使用区域,除了一些大型视图模型外……WPF视图模型是一种特殊的情况,在这种情况下,我通常将私有字段放在每个公共属性的前面。在这种情况下,私有字段加上公共成员的集合是同一单位
zameb

15

我建议使用IDesignBrad Abram网站上列出的编码标准。这些是我发现的最好的两个。

布拉德会说...

类成员应按字母顺序排列,并分为几节(字段,构造函数,属性,事件,方法,专用接口实现,嵌套类型)


3
如今,该链接似乎仅指向IDesign主页。这些天看来,编码标准已隐藏在通过电子邮件发送的下载链接后面#justsaying
Liam,

准则应有理由。这样做的理由是:1.使您理解; 2.使您可以对边界,细微,模棱两可,不可预见或有冲突的情况进行判断; 3.使您可以在条件变化时进行调整,并且不再适用某些准则。
Pablo H

6

如前所述,C#语言中没有任何内容可以规定布局,我个人使用区域,而对于普通班级,我会这样做。

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

反正对我来说很有意义


19
这就是说(仅供参考)stylecop建议不要使用区域(SA1124 DoNotUseRegions)
Gerwald 2012年


1
@zwcloud当然,在具有5538行的文件中,区域是必需的,但这并不意味着您应该在普通文件中使用区域。
Ghost4Man

1
@Gerwald:我认为StyleCop仅适用于使用StyleCop的人。这是众多标准之一
-zameb

1
@zameb:我想说,StyleCop规则是C#最常见的编码准则之一。在使用任何语言进行编码时,我总是试图找到最常见的编码准则集并加以遵循。
Gerwald '18

5

从StyleCop

私有字段,公共字段,构造函数,属性,公共方法,私有方法

由于StyleCop是MS构建过程的一部分,因此您可以将其视为事实上的标准


有趣。您是否定期使用StyleCop?
mmcdole

对于一个项目,是的,因为它确实会不时地用于某些MS合同工作。这是非常令人讨厌的笑容
blowdart

1
长时间使用StyleCop并使用这些建议将使代码更易于阅读:如果打开类的.cs文件,我会立即看到比私有方法“更重要”的公共方法。公众是该课程提供的,可以进行测试的类的“接口”(首选TDD和Test-First)
hfrmobile 2012年

1
根据StyleCop的说法,公共字段应排在私有字段之前stylecop.com/docs/SA1202.html
Michael Freidgeim

1
“ StyleCop是MS构建过程的一部分”是什么意思?微软是否为其所有代码使用StyleCop?
Rico Suter 2014年

5

通常我会尝试遵循以下模式:

  • 静态成员(通常具有其他上下文,必须是线程安全的,等等)
  • 实例成员

每个部分(静态和实例)由以下成员类型组成:

  • 运算符(始终是静态的)
  • 字段(在构造函数之前初始化)
  • 构造函数
  • 析构函数(是遵循构造函数的传统
  • 属性
  • 方法
  • 大事记

然后,成员按可见性排序(从不可见到更可见):

  • 私人的
  • 内部
  • 内部保护
  • 受保护的
  • 上市

顺序不是教条:简单的类更易于阅读,但是,更复杂的类需要特定于上下文的分组。


5

我的偏好是按种类排序,然后降低可见度,如下所示

public methods
public events
public properties

protected methods
protected events
protected properties

private methods
private events
private properties
private fields

public delegates
public interfaces
public classes
public structs

protected delegates
protected interfaces
protected classes
protected structs

private delegates
private interfaces
private classes
private structs

我知道这违反了Style Cop,并且如果有人可以给我一个很好的理由,为什么我应该将类型的实现细节放在其接口之前,我愿意进行更改。目前,我非常希望将私人成员放在最后。

注意:我不使用公共或受保护的字段。


3
同意 我真的很想知道,将私有成员放在首位的想法是否不是C天的保留,因为C天必须先声明变量。我几乎总是想首先看到公共接口,而不是类内部。
马特·戴维斯

1
这实际上很有意义。我敢打赌,这是从C缓缴
Aluan哈达德

IMO可能是一些最大的陷阱。当您不知道吸气剂/设定剂上存在逻辑时,将更有可能咬伤方法中的副作用(您自然希望它们存在),因此,我更喜欢顶部的属性以及它们的字段,因此,当我第一次上课时,我会发现问题已经解决了。在阅读方法的过程中,无论如何
Ryan The Leach


3

我看到的唯一建议的编码准则是将字段放在类定义的顶部。

我倾向于把构造函数放在下一个。

我的一般评论是,您应该在每个文件中坚持一个类,如果该类足够大,以至于属性和方法的组织成为一个大问题,那么该类有多大,您是否应该重构它?它代表多个问题吗?


3
一旦需要区域...您就迷路了。
Hamish Smith

3

我更喜欢将私有字段与构造函数放在顶部,然后在其后放置公共接口位,然后是私有接口位。

另外,如果您的类定义足够长,以至于项目的排序很重要,那么这可能是代码气味,表明您的类过于庞大和复杂,您应该进行重构。


3

我尽量保持简单(至少对我来说)

枚举
声明
构造 方法
重写
方法
属性
事件处理程序


2

语言中肯定没有任何东西可以以任何方式强制执行它。我倾向于按照可见性(公共,然后受保护,然后私有)对事物进行分组,并使用#region在功能上对相关事物进行分组,无论它是属性,方法还是其他。构造方法(无论是实际的ctor还是静态的工厂功能)通常位于顶部,因为它们是客户首先需要了解的。


我也使用区域按可见性进行分隔,并且使用Regionerate代码布局使我很诚实。 rauchy.net/regionerate
被遗忘的分号

我没有发现使用#regions有问题,但是我经常发现,一旦我想放入一个区域,它就会提示我考虑拆分我的课程。
mikecamimo

2

我知道这很旧,但是我的订单如下:

按照公共,受保护,私有,内部,抽象的顺序

  • 常数
  • 静态变量
  • 领域
  • 大事记
  • 构造函数
  • 方法
  • 物产
  • 代表们

我也喜欢写出这样的属性(而不是速记方法)

// Some where in the fields section
private int someVariable;

// I also refrain from
// declaring variables outside of the constructor

// and some where in the properties section I do
public int SomeVariable
{
    get { return someVariable; }
    set { someVariable = value; }
}
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.