类实例=作用域+cls+变量名 类对象=C+名称
结构对象定义
结构对象实例=作用域+struc+变量名 结构对象=S+名称
命名空间定义 以层为前缀进行命名 接口定义 以大写I为前缀
窗体的命名规则
窗体名=frm+窗体名(名词+动词) 注意:保存的文件名和窗体名相同。
枚举定义规则 以Enum为前缀
事件命名规则
事件控制器要带有EventHandler后缀 使用sender和e命名两个参数 事件参数类要带有EventArgs后缀 考虑使用动词命名事件
对于有“之前”或“之后”概念的事件,要使用现在时或过去时命名
8 编程实践
8.1 书写顺序
书写类时,按照从上到下的顺序,类成员应该是域,构造函数,属性,方法。 8.2 成员可视性
类的域都应该是private,如果需要被外部访问,使用public属性进行访问。但也有例外:
? 如果类的域仅作为一种数据集合,可以将域设定
为public,这样的类不要有任何方法
? 常量域,静态域或静态常量域可以设定为public
- 11 -
? private是默认的类成员访问修饰符,可以省略,
但为了明确表达,应该书写出来。
8.3功能单一
类的功能要单一,不要组合没有直接关联的功能。方法也一样。一个方法只完成一个任务,不要把多个任务组合进一个方法,即使那些任务很小。就是说,应该以逻辑功能来界分类或方法。 8.4使用枚举
不要使用数字或字符串来指示离散值,应该使用枚举。 不好的:
void SendMail(string message, string mailType) {
switch (mailType) {
case \ …… break; case \ …… break; case \ …… break; default : …… break; } } 好的: enum MailType {
Html, PlainText, Attachment }
void SendMail(string message, MailType mailType) {
- 12 -
switch (mailType) {
case MailType.Html : …… break;
case MailType.PlainText : …… break;
case MailType.Attachment : …… break; default : …… break; } }
8.5 捕获异常
只捕获特定的异常,如读取外部文件,而不要捕获一般异常,有利于调试排错。 不要捕获了异常却什么也不做,应该做适当处理,并把结果反馈到界面。如果隐藏了一个异常,将很难知道异常到底发生了没有,或者在哪里发生的。
9.其他注意事项
1. 避免将多个类放在一个文件里面。
2. 一个文件应该只有一个命名空间,避免将多个命名空间放在同一个文件里面。 3. 一个文件最好不要超过500行的代码(不包括IDE产生的代码)。 4. 一个方法的代码长度最好不要超过25行。
5. 避免方法中有超过5个参数的情况。如果超过了,则应使用 struct 来传递多个参数。 6. 每行代码不要超过80个字符。
7. 原则上,尽量不要手工的修改机器产生的代码。
a) 如果需要编辑机器(IDE)产生的代码,编辑格式和风格要符合该编码标准。 b) 尽可能地使用片断类来把被保持的部分分解为各个因素
注:这里的翻译参考了灵感之源老兄的说法,在Visual c#2005中,C#的语法已经支持
partial修饰符,它的作用是可以将一个完整的类分解各个部分类,在编译时,编译器会将它们构造为一个类。
- 13 -
具体请参考
http://blog.joycode.com/zhanbos/archive/2004/05/25/22402.aspx http://weblogs.asp.net/jaybaz_ms/archive/2004/04/28/122392.aspx
8. 避免利用注释解释显而易见的代码。
a) 代码应该可以自解释。好的代码本身就应具体良好的可读性,所使用的变量和方法命名一般情况下不需要注释。
9. 文档应该仅用于assumptions, algorithm insights等等. 10. 避免使用方法级的文档。
a) 使用扩展的API文档进行说明。
b) 只有在该方法需要被其他的开发者使用的时候才使用方法级的注释。(在C#中就是///) 11. 不要硬编码数字的值,总是使用构造函数设定其值。
12. 只有是自然结构才能直接使用const(常量),比如一个星期的天数。
13. 区别只读变量及常量的使用方法,如果想实现只读变量,可以直接使用readonly 修饰符。 public class MyClass {
public readonly int Number; public MyClass(int someValue) {
Number = someValue; }
public const int DaysInWeek = 7; }
14. 每个假设必须使用Assert检查
a) 平均每15行要有一次检查(Assert) using System.Diagnostics;
object GetObject() {?}
object obj = GetObject(); Debug.Assert(obj != null);
15. 代码的每一行都应该通过白盒方式的测试。
- 14 -
16. 只抛出已经显示处理的异常。
17. 在捕获(catch)语句的抛出异常子句中(throw),总是抛出原始异常,用以维护原始错误的堆栈分配。
catch(Exception exception)
{
MessageBox.Show(exception.Message);
throw ; //和throw exception一样。
}
注:同理,不推荐在循环语句中,进行直接的return操作。 for (int i=0;i<100;i++) {
if (i==10) {
return; //不推荐的方式 } }
18. 避免方法的返回值是错误代码。 19. 尽量避免定义自定义异常类。 20. 当需要定义自定义的异常时:
a) 自定义异常要继承于ApplicationException。 b) 提供自定义的序列化功能。
21. 避免在单个程序集里使用多个Main方法。 22. 只对外公布必要的操作,其他的则为internal。
23. 避免使用友元程序集,因为它会增加程序集间的耦合度。 24. 避免编写从指定的位置加载的程序集的代码。
25. 使应用程序集尽量为最小化代码(EXE客户程序)。使用类库来替换包含的商务逻辑。 26. 避免给枚举变量提供显式的值。 //正确方法 public enum Color
- 15 -