1、C#代码规范范本 C#编码规范目 录方针该代码标准提供了相关软件开发项目中,使用C#进行编码时的规则,推荐代码标准,起到了一定的指示作用。为了使该标准制定的方针浅显易懂,用了简单的代码来编写。而在实际的编程中,是需要项目小组所有成员同意该编写规则的。对于实际项目,我们推荐将该标准以顾客为标准使用。还有,我们还推荐读者参考配合.NET Framework SDK帮助的面向对象开发设计指南。 特别是在Extreme Programming项目中没有认识到的,可使用其它C#编程的项目中运用。1. 代码注释规范(1) 文件功能,创建,修改信息注释(2) 类功能注释(3) 方法注释(4) 较长的注释,*
2、GY需要复数行注释的情况下,在最初用短小的篇章写上想要注释什么。然后在添加上长的注释。另外,在感觉有必要写象如此长的注释之时, 请再三考虑一下,可否将程序设计再简化一下。请积极地应对。2. 目录文件构成(5) 目录文件名Public类会生成一个以该类命名的文件。例:public class Customer里面有着Customer.cs。包内的非公共类,最好放在包含该类经常被使用的公共类目录文件下。对于特殊类,一个目录文件可以包含多个类。(6) 目录文件的位置决定了项目的根目录之后,在命名空间的“.”处输入导入目录的阶层位置。可是对应于solution/project的命名空间的阶层则用sol
3、ution名/project名作为目录名来使用。例:命名空间:CompanyName.OrganizationName.TechnologyName.CoreFeatureName.SubFeatureNameSolution SolutionName 所对应的命名空间:TechnologyNameProject ProjectName 所对应的命名空间:CoreFeatureName配置路径:C:CompanyNameOrganizationNameSolutionNameProjectNameSubFeatureName(7) TestClass名类ClassName的单元测试类是以Cla
4、ssNameTest来命名的。Solution的每个测试都是以SolutionNameTests来命名的。 例:如果是Customer类的测试类的话就命名为CustomerTest.cs。例:如果是CsSample的soultion的话,就把它命名为CsSampleTests.csproj。理由:因为是这样命名是非常有一致性。可以成为使用测试代码的样例和演示版。(8) TestClass的位置测试类的位置应配置在被测试类相同的阶层的目录下。例:被测试类的位置:测试类的位置:理由:如果不是物理位置较近的话,会被维护系统所遗漏。对于产品的代码分离这一点而言,用其他的工具(NAnt的build文件之
5、类)也是可能调整的。 3. 命名规则(9) NameSpace结构规范NameSpace分类和命名原则先根据解决方案(Solution)、业务系统(Application)、子系统(Sub)、模块(Module) 划分目录,然后在模块内部按照Web、Biz、integration层对NameSpace结构进行命名。Web层NameSpace命名规范 Beyondbit.Solution.Application.Sub.Module.Web业务层NameSpace命名规范 Beyondbit.Solution.Application.Sub.Module.Biz数据访问层NameSpace命名规
6、范 Beyondbit.Solution.Application.Sub.Data集成层NameSpace命名规范 Beyondbit.Solution.Application.Sub.Module.BizCommon该目录应用于解决方案(Solution)、业务系统(application)、子系统(sub),存放在一些与业务相关的通用处理程序,可以视为公共的模块,可包含Web、Biz、integration。Util该目录应用于解决方案(Solution)、业务系统(Application)、子系统(Sub),存放在一些与业务无关的通用处理程序。(10) 文件名Public类的命名一定要与
7、文件名同名(包括大,小写的区别)。(11) 类名类名使用Pascal大小写形式。(12) 异常类名最后以Exception结尾。(13) 接口名与类名相同。此外,经常在最前面添加I。interface IClassName此外,在使用添加了某项功能的情况下,我们要加上可以表示这种功能的形容词,以-able结尾。例: IEnumerable, ICloneable, IXmlSerializable, (14) 抽象类名如果没有适合抽象类名的名字的时候,就联想以Abstract为开头的Subclass名作为抽象类的名字。abstract class AbstractBeforeSubClassN
8、ame(15) 常量(Const)用大写或者大写后加“_”。 const int UPPERCASE = 0;const int UPPERCASE_WITH_UNDERSCORES = 0;(16) 枚举型(enum)枚举名使用Pascal大小写格式。enum PascalCasing枚举型在表示位域的时候用复数。并附加FlagsAttribute。 Flags enum PascalCasings(17) 枚举值枚举值使用Pascal大小写格式。PascalCasing(18) 事件名事件名使用Pascal大小写格式。 event PascalCasing()(19) 方法名方法名使用Pa
9、scal大小写格式。void PascalCasing()object PascalCasing()(20) factory方法 (生成新的对象)X NewX()X CreateX()(21) 转换方法(把一个对象转换成别的对象) X ToX()(22) 属性名属性名使用Pascal大小写形式。 object PascalCasing(23) Boolean变量返回方法Is + 形容词、Can + 动词、Has + 过去分词、三单元名词、三单元动词 + 名詞。好的例子:bool IsEmpty()bool CanGet()bool HasChanged()bool Contains(objec
10、t x) bool ContainsKey(string key)bool CheckUserRight(string userId,string rightId)不好的例子:bool Empty() /方法调用者会理解成“清空”的意思。理由:方法调用者很容易理解if,while等条件语句的条件。另外,也很容易理解ture意味着什么。(24) Bool变量形容词、is+形容词、can+动词、has+过去分词、三单元动词、三单元动词名词。形容詞、is + 形容詞、can + 動詞、has + 過去分詞、三単元動詞、三単元動詞 + 名詞。bool isEmpty;bool dirty;bool c
11、ontainsMoreElements;(25) 英语和中文所有的关键词名都是以英语为基础,另外,在整个项目的制作周期中都有中英对照字典的支持。(26) 命名的对称性要取类名,方法名的时候请注意以下的英语的对称性。Add / RemoveInsert / DeleteGet / SetStart / StopBegin / EndSend / ReceiveFirst / LastGet / ReleasePut / GetUp / DownShow / HideSource / TargetOpen / CloseSource / DestinationIncrement / Decreme
12、ntLock / UnlockOld / NewNext / Previous (27) 循环计数器对于应用Scope(适用范围)的局部循环计数器,以,为顺序依次命名。(28) Scope的局部变量命名Scope的局部变量名最好使用其类型名的缩写。例: DataSet ds = new DataSet();(29) 有意义的命名最好使用从名字中就可以看出其变量作用的变量名。不好的例子: Copy(string s1, string s2)好的例子: Copy(string source, string destination)(30) 无意义的命名用Info, Data, Temp, Str,
13、 Buf这些做变量名的时候需要再三考虑。不好的例子:double temp = Math.Sqrt(b*b - 4*a*c);好的例子:double determinant = Math.Sqrt(b*b - 4*a*c);(31) private / protected / internal / protected internal scope的实例变量使用Camel大小写形式。我们需要考虑的是使变量更加容易读懂。private object camelCasing;protected object camelCasing;internal object camelCasing;protec
14、ted internal object camelCasing;(32) public scope的实例变量使用Pascal大小写形式。开头用大写。 public object PascalCasing;(33) private / protected / internal / protected internal scoope的公共变量使用Camel大小写形式。我们要考虑使得变量更加容易读懂。private static object camelCasing; protected static object camelCasing;internal static object camelCa
15、sing;protected internal static object camelCasing;(34) public scope的公共变量使用Pascal大小写形式。public static object PascalCasing;(35) Local变量使用Camel大小写形式。 object camelCasing;(36) 大写与小写 大写与小写被作为不同的文字被使用。仅仅因为这个区别我们就不得不注意名字的取法。4. 代码编写(37) #Region / #End Region directive代码域要声明 #Region / #End Region directive,要包含
16、这个域相关的说明。 例:#Region 实例变量 private string name; #End Region #Region Constract public MyClass(string name) this.name = name; #End Region(38) 声明 方法/属性声明方法/属性要明确指出scope。(39) 较长的行一行最多100位,如果有超过的情况要分割行。分行指针通过逗号另起一行。 例:double length = Math.Sqrt(Math.Pow(new Random().NextDouble(), 2.0) + Math.Pow(new Random(
17、).NextDouble(), 2.0); double length = Math.Sqrt(Math.Pow(new Random().NextDouble(), 2.0), Math.Pow(new Random().NextDouble(), 2.0);(40) 较长的类的声明类声明较长的情况下,请换成多行。例:public class LongNameClassImplemenation : AbstractImplementation, IXmlSerializable, Icloneable那么请变为:public class LongNameClassImplemenation
18、 :AbstractImplementation,IXmlSerializable, ICloneable(41) 较长的方法声明方法声明较长的情况下,请换成多行。 例: public void LongMethodSignature(int a, int b, int c, int d, int e, int f) (42) abstract Class vs. interface请尽量不要使用抽象类(abstract class),多使用interface。abstract class是有体方法与抽象方法的结合使用。理由:一个类可以实现很多接口,却只能继承一个抽象类。一个类继承之抽象类后就
19、不能继承其他的类,会造成浪费。(43) public Variable类变量请不要频繁将其设为public的作用域,请将它设置为合适的作用域。理由:这是面向对象的标准。随意地访问类的内部状态是不好的。可是,在满足以下全部条件时,类的public变量可以直接访问。 该类变量独立于其他的类变量,单独变更其内容的话,是不会对内部的整合性造成影响的。 无论哪个,都要编写上get/set访问。 有证据说明类变量在实例化后不会变更。另外,遇到不适合上述情况的时候,如需要极度注重开发速度的情况。也不仅限于上述的标准。(可是,需要我们慎重地注释)(44) 初始化不要指望默认的初始化(比如将某些变量用null值
20、初始化之类)。另外,不要再次初始化。不好的例子:public class PoorInitialization private string name = initial_name; public PoorInitialization() name = initial_name; 理由:请把关于初始化的Bug减到最低。(45) 避免static变量请尽力避免static变量。理由:它使用了更加使上下文连贯的代码,覆盖隐藏了副作用。(46) private vs. protected比起private,我们应更多使用protected。 理由:private不让该类以外的其他类调用。客户无法对继
21、承此类的private的方法重新实现。别的方法:请选private使用。如果将属性变为protected之后,如果该类有变更的话,那么对全部继承它的类都会有影响。(47) get/set访问请避免随便地将实例变量的作用域(get/set访问)定为public的作用域。在这之前请讨论其必要性,将它做成更加有意义的属性/方法。理由:类变量经常依赖其他类变量。我们不能破坏类内部的整合性。(48) 隐藏变量隐藏变量名请避免和基本类中的变量名同名。理由:一般来说,会产生Bug。如果有特殊意义的话请注释一下。(49) Public方法类的public方法是以“自动贩卖机的界面”为目标,为了变得浅显易懂,即
22、使使用方法错误,也不会破坏其内部整合性而设计的。另外,如果可能的话,请根据协议而设计(Design by Contract),与类的不变条件一起,用代码表现方法的重载。(50) 获得状态与变更状态的分离 请将方法设计为执行“一种功能”。特别是,变更状态和获得状态这两种服务不能在一个方法内执行。请用void做为状态变更方法的返回值。理由1:只执行一件事情的方法比较容易理解。理由2:比较容易做到对于并发性的控制,异常的安全保证。理由3:根据子类化比较容易扩展。(51) this的返回 就算是为了客户的方便着想,也请尽量避免this的返回。理由:像A.Meth1().Meth2().Meth3()这
23、样的连锁,一般会变成Synchronization上问题的根源。(52) 方法的多重定义根据参数的类型不同,请尽量避免方法的重载(如果参数不相同的话是可以)。特别是,如果和继承挂钩的话会很麻烦。例:错误:override void Draw(Rectangle rectangle) override void Draw(Point point)正确:void DrawRectangle(Rectangle rectangle) void DrawPoint(Point point)(53) Equals()与GetHashCode()如果要重载Object.Equals()方法的话, 请同时重
24、载GetHashCode()方法。相反也一样。理由:为了对应容器类(Hashtable) (54) Clone()如果, 使用了Clone()方法的话, 实际装载ICloneable明确地书写。例:using System; public class Foo : ICloneable public object ICloneable.Clone() Foo myFoo = (Foo) this.Clone(); / Foo类属性的clone /. 理由:有许多例子表明简易的复制是不好的。(55) deflaut constract 如果可能的话,请都准备使用一个deflaut constrac
25、t(哪怕是没有参数)。理由:使用reflection, 用Assembly.CreateInstance(TypeName)从类型名字符串开始做成该动态类。(56) abstract Method in abstract classes对于abstract 类来说,比起书写no-op 的方法来,请明确地声明成abstract 方法。另外,如果可以准备好可能共享的default的实现的话,将其设为protected属性,请在子类中用一行书写处理方法。理由:.NET的IDE并没有实际实现。为了检测出abstract方法,可以回避仅仅忘记实际实现IDE的BUG。(57) 类型的变换 类型的变换请使用
26、Convert类。string str = 123456789; int num = Convert.ToInt32(str); int num = 123456789; string str = Convert.ToString(num); (58) 对象的同值比较对象比较 = 使用方法,不使用Equals。String的比较就使用=来比较。另外,比较独立对象的情况下,请按照如下的方式来实现独立对象:Equals, GetHashCode ,operator=,operator!=理由:如果使用Equals方法的话,源代码就会看上去比较混乱。 class Hoge private strin
27、g s; public Hoge(string s) this.s = s; public override bool Equals(Object a) return Equals(this.s, (Hoge)a).s); public static bool operator =(Hoge a, Hoge b) return Equals(a.s, b.s); public static bool operator !=(Hoge a, Hoge b) return !Equals(a.s, b.s); public override int GetHashCode() return s.G
28、etHashCode(); (59) 声明与初始化Local变量请和初始值一起声明。理由:请最小化关于变量值的设定。不好的例子:void f(int start) int i, j; / 没有声明初始值 / 许多代码 / . i = start + 1; j = i + 1; / 使用了i, j / . 好的例子:void f(int start) / 许多代码 / . int i = start + 1; int j = i + 1; / 使用了i, j / . (60) Local变量重复使用的坏处如果重复使用Local变量,应该声明新的变量并初始化。理由:关于变量值的假定应该最小化。理由
29、:对编译的优化有帮助。不好的例子:void f(int n, int delta) int i; /没有初始化的声明 for (i = 0; i n; i+) / 使用了i for (i = 0; i n; i+) / 再次使用了i if (.) break; if (i != n - 1) / 循环终止判定条件里面使用了i / . i = n - delta * 2; / 再次使用了i /. 好的例子: void f(int n, int delta) for (int i = 0; i n; i+) /使用了i bool found = false; for (int j = 0; i n; i+) / 使用了j if (.) found = true; break; if (found) / . int total = n - delta * 2; /有着其他意思的变量 /. (61) 大小比较运算符比较习惯使用“”、“”、“=”请尽量避免。理由:为了统一字符大小的方向,右边的字符大的话,可以避免混乱。(62) If/while条件中的“=”对于if,while的条件,不可以代入“=”使用。理由:几乎在所有这
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1