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

Posted

技术标签:

【中文标题】类中项目的顺序:字段、属性、构造函数、方法【英文标题】:Order of items in classes: Fields, Properties, Constructors, Methods 【发布时间】:2010-09-14 02:37:31 【问题描述】:

在类结构方面,项目的顺序是否有官方的 C# 指南?

它去吗:

公共领域 私有字段 属性 构造函数 方法 ?

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

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

任何提示/建议?

【问题讨论】:

其实,要回答实际问题,不,没有官方指南。 StyleCop 实施了为在 Microsoft 的一个特定组中使用而开发的指南。这不是官方指南,甚至可能在 Microsoft 的各个组之间不统一。 一个简单的技巧是在 .net 中查看一些复杂类的元数据(VS 中的 F12)。您将至少了解publicprotected 成员的订购方式。 这个问题不是基于意见的,因为它询问是否有官方指南。要么有指南,要么没有! @nawfal 我意识到这是一个老评论,我喜欢你提到的技巧,但值得一提的是它不会显示 privateinternal 成员(我相信)。但是,看到publicprotected 的方式很好。我们可以看到.NET Framework类的来源,这里referencesource.microsoft.com也是 【参考方案1】:

根据StyleCop Rules Documentation的顺序如下。

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

常量字段 字段 构造函数 终结器(析构函数) 代表 活动 枚举 接口(接口实现) 属性 索引器 方法 结构 类

在每个组中按访问顺序排列:(SA1202)

公开 内部 受保护的内部 受保护 私人

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

静态 非静态

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

只读 非只读

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

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

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

【讨论】:

感谢您在这篇文章中付出的努力。我试图让 StyleCop 的东西成为一个标准(即使只是为了保持一致并便于查找),这很有价值。 就我个人而言,我发现静态方法的排序很烦人。我可以看到首先出现静态公共方法的论点,但我通常希望在成员之后使用私有静态方法。毕竟它们是公用事业。 我喜欢部分类提示 只是关于部分类的注释。鉴于在编译期间所有部分都被编译为单一类型,我总是会尝试确保有充分的理由来创建额外的开销。部分类的主要原因是为了扩展自动生成源代码或在处理大型项目时允许多个开发人员处理同一个类但单独的文件。 @FrançoisWahl 编译器将部分类组合成单一类型的相关开销有那么大吗?【参考方案2】:

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

【讨论】:

如果使用 StyleCop 推荐的“排序”,这是一种功能。一些方法是公开的而另一些是私有的,这是有充分理由的。代码的可读性确实更好:如果打开一个类的 .cs 文件,我会立即看到比私有方法“更重要”的公共方法(对于使用该类的人) 如果你的类中有这么多方法、属性等,你需要按部分对它们进行分组,这可能是这个类做得太多的迹象? 即使类很小,将公共方法与其对应的私有方法分组在一起是否有意义,这些私有方法仅由该公共方法调用? +1 如果公共方法 Foo() 调用受保护/私有 InternalFoo() ,那么第二种方法最好位于源代码中 DoFoo() 的正下方,而不是在其他受保护/私有的更下方方法。 按功能分组称为类【参考方案3】:

这是一个古老但仍然非常相关的问题,所以我将添加以下内容:当您打开一个您以前可能读过或可能没有读过的类文件时,您首先要查找的是什么?领域?特性?我从经验中意识到,我几乎总是在寻找构造函数,因为要了解的最基本的事情就是这个对象是如何构造的。

因此,我开始将构造函数放在类文件中,结果在心理上是非常积极的。将构造函数放在一堆其他东西之后的标准建议感觉不协调。

C# 6 中即将推出的主构造函数功能证明了构造函数的自然位置是在类的最顶端 - 事实上,主构造函数甚至在左大括号之前就已指定。

有趣的是,像这样的重新排序会产生多大的不同。它让我想起了 using 语句过去是如何排序的——首先是系统命名空间。 Visual Studio 的“组织使用”命令使用此顺序。现在usings 只是按字母顺序排列,没有对系统命名空间进行特殊处理。结果只是感觉更简单、更干净。

【讨论】:

在我看来,类初始化/构造很复杂。字段在显式构造函数运行之前被初始化,因此进一步按照你的论点将成员按使用/创建的顺序放置,初始化的字段将在显式声明的构造函数之前。初始化的静态字段和静态构造函数让它变得更加有趣。 实际上,人们倾向于寻找它们的顺序,即代码首先应该被人类阅读的文学编程概念。 请注意,主要构造函数已从 C# 6 的计划中删除:***.com/a/26915809/5085211 10 次中有 9 次在寻找公共接口,这就是为什么我将所有公共成员放在首位,然后是内部成员,然后是受保护成员,最后是私有成员。 @DavidCulp:我认为他并不是说他想查看一个类的初始化顺序,他不是编译器而是人类。他想“了解这个对象是如何构造的”,这是可以理解的。他可能需要这个类,并且想查看依赖关系以及它真正需要什么。【参考方案4】:

我不了解语言或行业标准,但我倾向于按此顺序排列,每个部分都包含在#region 中:

使用语句

命名空间

私人会员

公共属性

构造函数

公共方法

私有方法

【讨论】:

这正是我的做法。除了类成员和私有成员之间,我有任何公共常量和枚举等。 是的,我更喜欢在私有方法之后保留公共属性。其他人更喜欢将构造函数放在公共属性之前......但在我的脑海中,我更喜欢按顺序排列值/构造函数/行为。然后“值”被划分为常量/私有成员/属性等。通常我不使用区域,除了一些大的视图模型......好吧,WPF 视图模型有点特殊,在这种情况下,我通常将支持私有字段放在每个公共属性之前。在这种情况下,私有字段加上公共成员的集合是同一个单元 如果您的班级足够大以至于需要区域来帮助查找内容,那么这表明您的班级太大了。【参考方案5】:

我建议使用IDesign 或Brad Abram's website 中列出的编码标准。这是我找到的最好的两个。

布拉德会说……

类成员应按字母顺序排列,并分组为部分(字段、构造函数、属性、事件、方法、私有接口实现、嵌套类型)

【讨论】:

该链接最近似乎只是指向 IDesign 主页。这些天,编码标准似乎隐藏在电子邮件下载链接后面#justsaying 指南应该有理由。这样做的理由是:1. 让你理解; 2. 让你可以对边缘的、微妙的、模棱两可的、不可预见的或冲突的情况进行判断; 3. 以便在条件发生变化和某些准则不再适用时进行调整。 【参考方案6】:

通常我尝试遵循下一个模式:

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

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

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

然后成员按可见度排序(从少到多可见):

私人 内部 内部保护 受保护 公开

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

【讨论】:

【参考方案7】:

如前所述,C# 语言中没有任何内容规定布局,我个人使用区域,并且我为普通班级做这样的事情。

public class myClass

#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion

对我来说还是有意义的

【讨论】:

这里是说(仅供参考)stylecop 不建议使用区域(SA1124 DoNotUseRegions) Microsoft itself is using regions. @zwcloud 当然,在 5538 行的文件中,区域是必需的,但这并不意味着您应该在普通文件中使用区域。 @Gerwald:我认为 StyleCop 仅适用于使用 StyleCop 的人。它是众多标准之一 @zameb:我想说,StyleCop 规则是 C# 最常见的编码准则之一。在使用任何语言进行编码时,我总是试图找到最常见的编码准则集并遵循它们。【参考方案8】:

我的偏好是按种类订购,然后按如下方式降低知名度

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,如果有人能给我一个很好的理由,为什么我应该将类型的实现细节放在它的接口之前,我愿意更改。目前,我强烈倾向于将私有成员放在最后。

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

【讨论】:

同意。我真的想知道将私有成员放在首位的概念是否不是 C 时代必须首先声明变量的保留。我几乎总是希望首先看到公共接口,而不是类内部。 这实际上很有意义。我敢打赌这是 C 的保留。 一些最大的问题可能是 IMO 属性。当您不知道的 getter/setter 上存在逻辑时,这将更有可能在方法中产生副作用(您自然希望它们存在)因此,我更喜欢属性与顶部的字段一起使用,所以当我第一次看课程时,我看到了问题。当我阅读方法时,我通常会立即导航/跳转到方法无论如何【参考方案9】:

来自 StyleCop

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

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

【讨论】:

有趣。你经常使用 StyleCop 吗? 对于一个项目是的,因为它确实会不时用于一些 MS 合同工作。很烦咧嘴 长时间使用 StyleCop,如果使用该建议使代码的可读性更好:如果打开一个类的 .cs 文件,我会立即看到比私有方法“更重要”的公共方法。公众是类的“接口”,它提供什么以及可以测试什么(更喜欢 TDD 和 Test-First) 根据 StyleCop,公共字段应该排在私有字段之前 stylecop.com/docs/SA1202.html “StyleCop 是 MS 构建过程的一部分”是什么意思?微软是否在其所有代码中使用 StyleCop?【参考方案10】:

您可能找到的最接近的是 Brad Abrams 的“设计指南、托管代码和 .NET 框架”(http://blogs.msdn.com/brada/articles/361363.aspx)

这里列出了许多标准。我认为相关部分是 2.8。

【讨论】:

【参考方案11】:

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

另外,如果你的类定义足够长以至于项目的排序很重要,那可能是 code smell 表明你的类太庞大和复杂,你应该重构。

【讨论】:

【参考方案12】:

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

枚举 声明 构造函数 覆盖 方法 属性 事件处理程序

【讨论】:

【参考方案13】:

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

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

常量 静态变量 字段 活动 构造函数 方法 属性 代表

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

// 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; 

【讨论】:

【参考方案14】:

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

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

我的一般意见是你应该坚持每个文件一个类,如果类足够大以至于属性与方法的组织是一个大问题,那么类有多大,你是否应该重构它?是否代表多个问题?

【讨论】:

一旦你需要区域......你就输了。【参考方案15】:

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

【讨论】:

我也使用区域来按可见性进行分隔,并且使用 Regionerate 代码布局让我诚实。 rauchy.net/regionerate 我认为使用#regions 没有问题,但我经常发现,一旦我想加入某个区域,它就会提示我考虑拆分课程。跨度> 【参考方案16】:

对于我认为更好的布局,我已经重新构建了已接受的答案:

在类、结构或接口中:

常量字段 只读字段 字段 活动 属性 索引器 构造函数 终结器(析构函数) 接口(接口实现) 方法 类 结构 枚举 代表

在每个组中按访问顺序排列:

公开 内部 受保护的内部 受保护 私人

在每个访问组中,按静态排序,然后是非静态:

静态 非静态

我也觉得嵌套类型应该保持在最低限度。我经常看到人们有嵌套的类、枚举、委托,它们最好是一个单独的实例。使类型嵌套几乎没有任何好处。也将它们放在单独的文件中。一个包含 5 个类的文件让我感觉很混乱。

【讨论】:

以上是关于类中项目的顺序:字段、属性、构造函数、方法的主要内容,如果未能解决你的问题,请参考以下文章

结构和类

java怎么调用带参数构造函数

类和结构体的区别

Java类中各个成员初始化顺序

构造函数是在 C# 中初始化类中不可为空的属性的唯一方法吗?

实体类中构造函数的疑问