是否有关于分类结构的项目顺序的官方C指南?
它去了吗?
我很好奇是否有一个关于物品顺序的硬性和快速的规则?我到处都是。我想坚持一个特定的标准,这样我可以在任何地方都能做到。
真正的问题是,我的更复杂的属性最终看起来很像方法,它们在构造函数之前感觉不在顶部。
有什么建议吗?
- 实际上,要回答实际问题,没有官方的指导方针。StyleCop实现了为在Microsoft的一个特定组中使用而开发的指导原则。这不是一个官方的指导方针,甚至可能在微软的集团中也不统一。
- 一个简单的技巧是在.NET中查看一些复杂类的元数据(Vs中的F12)。您将了解它是如何至少为public和protected成员订购的。
- 这个问题不是基于意见的,因为它询问是否有官方的指导方针。要么有指导方针,要么就没有!
根据StyleCop规则文档,顺序如下。
在类、结构或接口中:(SA1201和SA1203)
- 恒定场
- 领域
- 构造函数
- 终结器(析构函数)
- 代表们
- 事件
- 枚举类型
- 接口(接口实现)
- 性质
- 索引器
- 方法
- 结构体
- 班
在这些组中,按访问顺序排列:(SA1202)
在每个访问组中,按静态顺序排列,然后按非静态顺序排列:(SA1204)
在每个静态/非静态字段组中,按只读顺序排列,然后按非只读顺序排列:(SA1214和SA1215)
展开的列表有130行长,所以我不会展开它。展开的方法是:
- 公共静态方法
- 公共方法
- 内部静态方法
- 内部方法
- 受保护的内部静态方法
- 受保护的内部方法
- 受保护的静态方法
- 受保护的方法
- 私有静态方法
- 私有方法
文档注意到,如果指定的顺序不合适(例如,正在实现多个接口,并且接口方法和属性应分组在一起),那么使用分部类将相关的方法和属性分组在一起。
- 我想感谢你在这篇文章中所做的努力。我正试图让StyleCop的东西成为一个标准(即使只是为了保持一致,让找到东西变得容易),这是很有价值的。
- 就我个人而言,我觉得静态方法的排序很烦人。我可以看到静态公共方法的参数首先出现,但我通常希望在成员之后使用私有静态方法。毕竟它们是公用事业。
- 谢谢,这对我的StyleCop辅助插件(sweeper.codeplex.com)的最新更改有很大帮助。唯一需要指出的是,许多元素类型不支持静态。
- 什么是只读字段?
- 我喜欢小费
- 只是一个关于部分类的注释。考虑到在编译期间,所有的部分都被编译成一个类型,我将始终尝试确保创建额外开销的一个很好的理由。部分类的主要原因是扩展自动生成的源代码,或者在处理大型项目时,允许多个开发人员处理同一个类但不同的文件。
- @fran&231;oiswahl是编译器将部分类组合成单个大类型所带来的开销吗?
- @Dav_I:如果开销很明显或者不明显,我真的不知道,我还没有对此进行任何性能测试。它很可能不明显,但作为一般经验法则,我尝试在扩展自动生成的代码时只创建部分。这里还有一个关于部分的好资源:4guysfromrolla.com/articles/071509-1.aspx
- @Fran&231;Oiswahl我认为开销不算太大,而且可读性的好处从长远来看会为您节省更多时间:)有趣的文章-我没有意识到存在部分方法!
- 另一点。在public static fields等中分组的标准方式是什么?即先按字段名还是按类型再按字段名?(如public int a; public bool b;或public bool b; public int a;?
- 我唯一避免的就是拆分字段及其关联的访问器属性。我把这种配对看作是一个领域。
- "接口"(在枚举和属性之间)是什么意思?显式接口实现还是…?
- @Fran&231;Oiswahl-在我的大型项目中,我经常使用部分类。我注意到绝对没有编译开销,最大的项目是大约60万条线路。我不喜欢有一个带有几十个访问器和方法的类。在大型类中,我将把它分成单独的.cs文件,每个方法一个。我发现这也使得查看解决方案资源管理器和立即在一个类中直观地查看所有可用方法变得更简单,而不必打开文件并扫描它。
- @迪吉,我目前正在与大约60名左右的开发人员合作一个大型项目。我们停止使用分部类,除非需要扩展自动生成的代码。当测试我们的代码时,这变得不切实际,因为20个分部类仍然是1个单一的大规模类。在自动化测试过程中,必须实例化一个这样大的类会大大降低测试的执行速度。它还向我们强调,在这些类中,我们没有遵循单一责任原则,而是将许多东西塞进了一个应该被分离的类中。请注意,这种规模的项目很少。
- 我把这个打印出来,挂在我的工作场所。
- 你和警察规则的联系被破坏了。
- stylecop订购规则可以在github.com/visual stylecop/visual stylecop/wiki/ordering rul‌&8203;es中找到。
- 谢谢你的回答。有一件事我觉得很奇怪,那就是枚举的位置。我一直把它们看作常数的变化(概念上),有人知道这里的动机是什么吗?将内部类型分组在一起?尽管我发现在类的末尾放置的内部类/结构也很奇怪。
- 我不喜欢这道菜。对我来说毫无意义。为什么接口和类相距如此之远?如果一个私有方法只在属性设置器中使用,我为什么要把它放远呢?为什么要将自动实现的属性放在远离字段的地方?看起来有人只是为了保持一致而随机选择了一个顺序。
- 对于"新的"c自动属性,我不太喜欢字段->构造函数->属性顺序,我觉得如果只有1或2个属性,那么这些属性应该出现在字段之后。虽然很难将"一两个"作为一个确定的规则,所以我一直遵循这个规则…
- @谢尔盖·塔奇诺夫和所有人。我一点也不喜欢点菜。如果类中的某个方法不能按我想要的方式工作,我将为该方法创建一个测试(进一步的方法A)。方法A使用其他一些私有方法B。如果我的测试需要存根方法B,我将方法B的访问修饰符更改为"受保护的虚拟内部"。为什么我要移动这个方法,即使它没有改变?我刚更改了访问修饰符,以便能够进行存根/模拟。源代码管理中该方法的更改历史将发生什么?查看这种方法的历史是不方便的。
- 有人知道这是否可以作为一个重新分析的布局文件?
- 哎哟!这样想真让我头疼(Stylecop)!我会保持我的方式,因为它更加用户友好:字段、属性和方法按这个顺序排列在一起(因为它们是最常见的),在那之前的一切。然后是私有的、受保护的和公共的(因为可见性增加,并且按字母顺序排列)。这是我的偏好,我已经习惯了。但我多年来养成了自己的习惯。它让我井然有序。如果你觉得好的话,就按你的顺序做。不要强迫自己承受压力!
- 此外,转换(强制转换)成员应放在索引器之后,然后放在运算符成员之后。
- 我想补充一点,我喜欢在类的顶部定义事件,因为我觉得它可以给出对象如何与其他对象通信、它拥有什么类型的属性以及它封装了什么类型的功能的总体概念。
与其按可见性或项目类型(字段、属性、方法等)分组,不如按功能分组?
- 如果使用StyleCop建议进行"排序",则这是一种功能。有些方法是公开的,有些方法是私有的,这是有充分理由的。代码的可读性确实更好:如果打开一个类的.cs文件,我会立即看到公共方法,它比私有方法"更重要"(对于使用该类的人来说)。
- 如果你的类中有如此多的方法、属性等,你需要按节对它们进行分组,这可能是类做得太多的一个标志?
- 即使类很小,用只由这个公共方法调用的相应的私有方法对公共方法进行分组是否有意义?
- +1如果public方法foo()调用一个protected/private internalfoo(),那么第二个方法最好位于源中dofoo()的正下方,而不是其他protected/private方法的正下方。
- 按功能分组称为类
- + 1。如果您所说的不同功能是"业务功能",那么我不同意。但是,如果它是"实用功能",那么它可能是有意义的。比如说,你的类有一个单一的业务含义,但是它是IEnumerable、IDisposable和InotifyPropertiesChanged,每个接口的实现需要比一个方法稍微多一些,那么即使整个类贡献了相同的业务功能,将它们组合在一起也可能是有意义的。
- 我叫我老派,但我会按从不太可见到更可见的访问顺序排序——我认为这是来自旧语言,在那里,其他人访问的函数必须先被编写。
- @Dosu先生,同意……所以如果你必须在课堂上分组,那么课堂太大了。
- 我们可以临时按功能分组,然后稍后重构。使用区域可以保持代码的整洁,并作为重构的提示。我认为,这就是以这种方式使用区域的目标。
这是一个古老但仍然很相关的问题,所以我要补充一点:当你打开一个你以前可能读过或没有读过的类文件时,你首先要找的是什么?领域?属性?我从经验中认识到,几乎总是要寻找构造函数,因为最基本的理解是如何构造这个对象。
因此,我开始将构造函数放在类文件中的第一位,结果在心理上非常积极。把构造器放在其他事情之后的标准建议感觉不协调。
C 6中即将出现的主要构造函数特性提供了一个证据,证明构造函数的自然位置在类的最顶端——事实上,甚至在左大括号之前就已经指定了主要构造函数。
有趣的是,像这样重新排序有多大的区别。它提醒了我以前如何对using语句进行排序——首先使用系统名称空间。Visual Studio的"Organize using"命令使用了此顺序。现在,usings只是按字母顺序排列,没有对系统名称空间进行特殊处理。结果只是感觉简单和干净。
- 在我看来,类初始化/构造是复杂的。字段在显式构造函数运行之前被初始化,所以在您的参数中,本质上是按照成员的使用/创建顺序放置成员,初始化的字段将在显式声明的构造函数之前。初始化的静态字段和静态构造函数使它更加有趣。
- 事实上,他们往往被人类寻找的顺序,文学编程的概念,即代码应该首先被人类阅读。
- 请注意,已从C 6:stackoverflow.com/a/26915809/5085211的计划中删除了主要构造函数。
- 10次中有9次,我在寻找公共接口,这就是为什么我把所有公共成员放在第一位,其次是内部成员,其次是受保护的成员,最后是私人成员。
我建议使用IDesign或BradAbram网站上列出的编码标准。这是我找到的最好的两个。
布拉德会说…
Classes member should be alphabetized, and grouped into sections (Fields, Constructors, Properties, Events, Methods, Private interface implementations, Nested types)
- 这些天,这个链接似乎只是指向IDesign主页。现在看来,编码标准隐藏在电子邮件下载链接后面。
- 指导方针应该有道理。理由是:1.让你明白,2.这样你就可以对边界、微妙、模棱两可、不可预见或冲突的情况进行判断。这样,您就可以在条件发生变化时进行调整,并且某些准则不再适用。
我不知道语言或行业标准,但我倾向于按此顺序排列,每个部分都包装在一个区域中:
使用语句
命名空间
等级
私人成员
公共财产
构造函数
公共方法
私有方法
- 我也是这样做的。除了在类和私有成员之间,我还有任何公共常量和枚举等。
- 是的,我更喜欢在私有方法之后保留公共属性。其他人更喜欢将构造函数放在公共属性之前…但在我的头脑中,我更喜欢按顺序拥有值/构造函数/行为。然后"值"被划分为常量/私有成员/属性等。通常我不使用区域,除了一些大视图模型…嗯,WPF视图模型有点特别,在本例中,我通常将支持私有字段放在每个公共属性之前。在这种情况下,私有字段集加上公共成员是同一个单元
如前所述,在C语言中没有规定布局的内容,我个人使用区域,我为一个普通类做类似的事情。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class myClass
{
#region Private Members
#endregion
#region Public Properties
#endregion
#region Constructors
#endregion
#region Public Methods
#endregion
} |
不管怎样,这对我来说是有意义的
- 这里是说(仅供参考),StyleCop不建议使用区域(SA1124 DonotUserRegions)
- 微软自己也在使用地区。
- @zwcloud当然,在一个有5538行的文件中,区域是必需的,但这并不意味着您应该在普通文件中使用区域。
- @格瓦尔德:我认为样式警察只适合使用样式警察的人。这是许多标准中的一个
- @Zameb:我想说,样式警察规则是C最常见的编码准则之一。当用任何语言编码时,我总是试图找到最常见的一组编码准则,并遵循它们。
通常我尝试遵循下一个模式:
- 静态成员(通常有其他上下文,必须是线程安全的,等等)
- 实例成员
每个部分(静态和实例)由以下成员类型组成:
- 运算符(始终是静态的)
- 字段(在构造函数之前初始化)
- 构造函数
- 析构函数(是遵循构造函数的传统)
- 性质
- 方法
- 事件
然后按可见性(从低到高)对成员排序:
顺序不是教条:简单类更容易阅读,但是更复杂的类需要上下文特定的分组。
来自StyleCop
私有字段、公共字段、构造函数、属性、公共方法、私有方法
因为StyleCop是MS构建过程的一部分,所以您可以将其视为事实上的标准。
- 有趣。你经常使用样式警察吗?
- 对于一个项目,是的,因为它经常被用于一些MS合同工作。很讨厌的笑容
- 长时间使用StyleCop,如果使用这些建议,代码的可读性会更好:如果打开类的.cs文件,我会立即看到比私有方法"更重要"的公共方法。公共接口是类的"接口",它提供什么以及可以测试什么(首选TDD,首先测试)
- 根据StyleCop,公共字段应先于私有字段StyleCop.com/docs/sa1202.html。
- "样式警察是MS构建过程的一部分"是什么意思?微软是否对其所有代码都使用样式表?
我的偏好是按种类排序,然后按如下方式降低可见性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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 |
我知道这违反了样式cop,如果有人能给我一个很好的理由,为什么我应该将类型的实现细节放在我愿意更改的接口之前。目前,我更倾向于把私人会员排在最后。
注意:我不使用公共或受保护的字段。
- 同意。我真的很想知道,将私有成员放在第一位的概念,是否不是从必须首先声明变量的C天开始的延迟。我几乎总是希望首先看到公共接口,而不是类内部。
- 这其实很有道理。我敢打赌这是C的延期。
- 一些最大的错误可能是IMO属性。当getter/setter上有您不知道的逻辑时,这将更容易在方法(您自然希望它们在方法中)中咬到副作用,因此,我更喜欢在顶部字段旁边的属性,所以当我为第一个IME,我看到了最新消息。当我读到一个方法时,我通常会立即导航/跳转到该方法。
你最可能找到的是Brad Abrams的"设计指南、托管代码和.NET框架"(http://blogs.msdn.com/brada/articles/361363.aspx)。
这里概述了许多标准。我想相关章节是2.8节。
我尽量保持简单(至少对我来说)
枚举声明构造函数重写方法性质事件处理程序
我更喜欢将私有字段和构造函数放在顶部,然后将公共接口位放在后面,然后放私有接口位。
另外,如果类定义足够长,以至于项目的排序非常重要,那么这可能是一种代码味道,表明您的类太庞大和复杂,您应该重构。
我看到的唯一的编码指导原则就是将字段放在类定义的顶部。
我倾向于把建设者放在后面。
我的一般性意见是,您应该坚持每个文件一个类,如果类足够大,以至于属性和方法的组织是一个大问题,那么类有多大,您应该重构它吗?它是否代表多个关注点?
我知道这是旧的,但我的顺序如下:
按公共、保护、私人、内部、抽象的顺序
- 常量
- 静态变量
- 领域
- 事件
- 构造函数(s)
- 方法
- 性质
- 代表们
我还喜欢写出这样的属性(而不是速记方法)
1 2 3 4 5 6 7 8 9 10 11 12
| // 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; }
} |
当然,语言中没有任何东西可以以任何方式强制它。我倾向于按可见性(公共、受保护、私有)对事物进行分组,并使用区域在功能上对相关事物进行分组,不管它是属性、方法还是其他。构造方法(无论是实际的ctors还是静态的工厂函数)通常都是最重要的,因为它们是客户需要了解的第一件事。
- 我也使用区域来按可见性进行分隔,并且有一个区域代码布局可以让我保持诚实。rauchy.net/地区
- 我不认为使用区域有问题,但是我经常发现只要我想放入一个区域,它就会提示我考虑将类拆分。