一、概述
为提高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可测试、高效、可移植的代码,编程规范修订工作组分析、总结各种典型编码问题,并参考了业界编程规范近年来的成果,重新进行了梳理、优化、刷新,微软官方给出一下C#编程规范。
1.1 结构清晰第一
清晰性是易于维护、易于重构的程序必需具备的特征。代码首先是给人读的,好的代码应当可以像文章一样发声朗诵出来。
目前软件维护期成本占整个生命周期成本的40%~90%。根据业界经验,维护期变更代码的成本,小型系统是开发期的5倍,大型系统(100万行代码以上)可以达到100倍。业界的调查指出,开发组平均大约一半的人力用于弥补过去的错误,而不是添加新的功能来帮助公司提高竞争力。
“程序必须为阅读它的人而编写,只是顺便用于机器执行。”——Harold Abelson 和 Gerald Jay Sussman
“编写程序应该以人为本,计算机第二。”——Steve McConnell
一般情况下,代码的可读性高于性能,只有确定性能是瓶颈时,才应该主动优化。
1.2 简洁之风
简洁是易于理解并且易于实现。代码越长越难以看懂,也就越容易在修改时引入错误。写的代码越多,意味着出错的地方越多,也就意味着代码的可靠性越低。因此,我们提倡大家通过编写简洁明了的代码来提升代码可靠性。
废弃的代码(没有被调用的函数和全局变量)要及时清除,重复代码应该尽可能提炼成函数。
本规范通过后文中的原则(如文件应当职责单一/一个函数仅完成一件功能)、规则(重复代码应该尽可能提炼成函数/避免函数过长,新增函数不超过50行)等说明简洁的重要性。
1.3 代码风格保持一致性
产品所有人共同分享同一种风格所带来的好处,远远超出为了统一而付出的代价。在公司已有编码规范的指导下,审慎地编排代码以使代码尽可能清晰,是一项非常重要的技能。**如果重构/修改其他风格的代码时,比较明智的做法是根据现有代码的现有风格继续编写代码,**或者使用格式转换工具进行转换成公司内部风格。
二、命名约定
微软官方规定,C#程序对类型名称、命名空间和所有公共成员使用PascalCase
命名规范。此外DotNet团队使用从DotNet Runtime团队的编码风格
中吸收的以下约定:
- 接口名称以大写字母
I
开头 - 属性类型以单词Attribute结尾
- 枚举类型对非标记使用单数名词,对标记使用复数名词
- 标识符不应包含两个连续的下划线 (_) 字符。 这些名称保留给编译器生成的标识符
- 对变量、方法和类使用有意义的描述性名称
- 清晰胜于简洁
- 将 PascalCase 用于类名和方法名称
- 将 camelCase 用于方法参数、局部变量和专用字段
- 将 PascalCase 用于常量名,包括字段和局部常量
- 专用实例字段以下划线(_)开头
- 静态字段以s_开头。此约定不是默认行为
- 避免在名称中使用缩写或首字母缩略词,但广为人知和广泛接受的缩写除外
- 使用遵循反向域名表示法的有意义的描述性命名空间
- 选择表示程序集主要用途的程序集名称,语法示例是规则的例外
- 将 S 用于结构,将 C 用于类。
- 将 M 用于方法。
- 将 v 用于变量,将 p 用于参数。
- 将 r 用于 ref 参数。
三、类型参数命名指南
以下准则适用于泛型类型参数上的类型参数。类型参数是泛型类型或泛型方法中参数的占位符。
3.1 请使用描述性名称命名泛型类型参数,除非单个字面名称完全具有自我说明性且描述性名称不会增加任何作用。
public interface ISessionChannel<TSession> { /*...*/ } public delegate TOutput Converter<TInput, TOutput>(TInput from); public class List<T> { /*...*/ }
3.2 对具有单个字面类型参数的类型,考虑使用T
作为类型参数名称
public int IComparer<T>() { return 0; } public delegate bool Predicate<T>(T item); public struct Nullable<T> where T : struct { /*...*/ }
3.3 在类型参数描述性名称前添加前缀 “T”
public interface ISessionChannel<TSession> { TSession Session { get; } }
3.4 考虑在参数名称中指示出类型参数的约束
四、总结
代码标准对于在开发团队中维护代码可读性、一致性和协作至关重要。 遵循行业实践和既定准则的代码更易于理解、维护和扩展。 大多数项目通过代码约定强制要求样式一致。使用命名空间限定。 如果你知道命名空间默认导入项目中,则不必完全限定来自该命名空间的名称。 如果对于单行来说过长,则可以在点 (.) 后中断限定名称。