-
c#编程规范(下)
6 第六章 语句
6.1 每行一个语句
每行最多包含一个语句。如
a++; //推荐
b--; //推荐
a++; b--; //不推荐
6.2 复合语句
复合语句是指包含"父语句{子语句;子语句;}"的语句,使用复合语句应遵循以下几点:
1)子语句要缩进。
2)左花括号“{” 在复合语句父语句的下一行并与之对齐,单独成行。
3)即使只有一条子语句也不要省略花括号“ {}”。 如
while (d + = s++)
{
n++;
}
6.3 return 语句
return语句中不使用括号,除非它能使返回值更加清晰。如:
return;
return myDisk.size();
return (size ? size : defaultSize);
6.4 if、 if-else、if else-if 语句
if、 if-else、if else-if 语句使用格式
if (condition)
{
statements;
}
if (condition)
{
statements;
}
else
{
statements;
}
if (condition)
{
statements;
}
else if (condition)
{
statements;
}
else
{
statements;
}
6.5 for、foreach 语句
for 语句使用格式
for (initialization; condition; update)
{
statements;
}
空的 for 语句(所有的操作都在initialization、condition 或 update中实现)使用格式
for (initialization; condition; update); // update user id
foreach 语句使用格式
foreach (object obj in array)
{
statements;
}
注意 1在循环过程中不要修改循环计数器。
2对每个空循环体给出确认性注释。
6.6 while 语句
while 语句使用格式
while (condition)
{
statements;
}
空的 while 语句使用格式
while (condition);
6.7 do - while 语句
do - while 语句使用格式
do
{
statements;
} while (condition);
6.8 switch - case 语句
switch - case 语句使用格式
switch (condition)
{
case 1:
statements;
break;
case 2:
statements;
break;
default:
statements;
break;
}
注意:
1)语句switch中的每个case各占一行。
2)语句switch中的case按字母顺序排列。
3)为所有switch语句提供default分支。
4)所有的非空 case 语句必须用 break; 语句结束。
6.9 try - catch 语句
try - catch 语句使用格式
try
{
statements;
}
catch (ExceptionClass e)
{
statements;
}
finally
{
statements;
}
6.10using 块语句
using 块语句使用格式
using (object)
{
statements;
}
7 控件命名规则
7.1 命名方法
控件名简写+英文描述,英文描述首字母大写。
7.2 主要控件名简写对照表
控件名 | 简写 | 控件名 | 简写 |
Label | lbl | TextBox | txt |
Button | btn | LinkButton | lnkbtn |
ImageButton | imgbtn | DropDownList | ddl |
ListBox | lst | DataGrid | dg |
DataList | dl | CheckBox | chk |
CheckBoxList | chkls | RadioButton | rdo |
RadioButtonList | rdolt | Image | img |
Panel | pnl | Calender | cld |
AdRotator | ar | Table | tbl |
RequiredFieldValidator | rfv | CompareValidator | cv |
RangeValidator | rv | RegularExpressionValidator | rev |
ValidatorSummary | vs | CrystalReportViewer | rptvew |
8 程序结构
8.1 程序结构规范
1)程序结构清晰,简单易懂,单个函数的程序行数不得超过100行。避免使用大文件。如果一个文件里的代码超过300~400行,必须考虑将代码分开到不同类中。避免写太长的方法。一个典型的方法代码在1~25行之间。如果一个方法发代码超过25行,应该考虑将其分解为不同的方法。一个文件应避免超过2000行。
2)打算干什么,要简单,直截了当,代码精简,避免垃圾程序。
3)尽量使用.NET库函数和公共函数(无特殊情况不要使用外部方法调用windows的核心动态链接库API)。
4)不要随意定义全局变量,尽量使用局部变量。
5)方法名需能看出它作什么。别使用会引起误解的名字。如果名字一目了然,就无需用文档来解释方法的功能了。
好:
void SavePhoneNumber ( string phoneNumber )
{
// Save the phone number.
}
不好:
// This method will save the phone number.
void SaveData ( string phoneNumber )
{
// Save the phone number.
}
6)程序编码力求简洁,结构清晰,避免太多的分支结构及太过于技巧性的程序。
7)避免采用过于复杂的条件测试,避免过多的循环嵌套和条件嵌套。
8)尽量使用.NET库函数和公共函数(无特殊情况不要使用外部方法调用windows的核心动态链接库API)。
9)不要随意定义全局变量,声明局部变量,并传递给方法。不要在方法间共享成员变量。如果在几个方法间共享一个成员变量,那就很难知道是哪个方法在什么时候修改了它的值。
10) 别在程序中使用固定数值,用常量代替。
8.2 结构书写规范
1)把所有系统框架提供的名称空间组织到一起,把第三方提供的名称空间放到系统名称空间的下面
using System;
using System.Collection.Generic;
using System.ComponentModel;
using System.Data;
using MyCompany;
using MyControls;
2)所有的类成员变量应该被声明在类的顶部,并用一个空行把它们和方法以及属性的声明区分开
public class MyClass
{
int m_Number;
string m_Name;
public void SomeMethod1();
public void SomeMethod2();
}
3)避免采用多赋值语句,如x = y = z;。
4)必要时使用enum 。别用数字或字符串来指示离散值。
好:
enum MailType
void SendMail (string message, MailType mailType)
{
switch ( mailType )
{
case MailType.Html:
// Do something
break;
case MailType.PlainText:
// Do something
break;
case MailType.Attachment:
// Do something
break;
default:
// Do something
break;
}
}
不好:
void SendMail (string message, string mailType)
{
switch ( mailType )
{
case "Html":
// Do something
break;
case "PlainText":
// Do something
break;
case "Attachment":
// Do something
break;
default:
// Do something
break;
}
}
5)一个方法只完成一个任务。不要把多个任务组合到一个方法中,即使那些任务非常小。
好:
void SaveAddress ( string address )
{
// Save the address.
// ...
}
void SendEmail ( string address, string email )
{
// Send an email to inform the supervisor that the address is changed.
// ...
}
不好:
void SaveAddress ( string address, string email )
{
// Job 1.
// Save the address.
// ...
// Job 2.
// Send an email to inform the supervisor that the address is changed.
// ...
}
6)使用括号清晰地表达算术表达式和逻辑表达式的运算顺序。如将 x=a*b/c*d 写成 x=(a*b/c)*d可避免阅读者误解为x=(a*b)/(c*d)。
7)总是使用以零为基数的数组。
8)把引用的系统的namespace和自定义或第三方的用一个换行把它们分开.
9)目录结构中要反应出namespace的层次.
9 异常处理
9.1 异常处理
1)不要“捕捉了异常却什么也不做”。如果隐藏了一个异常,你将永远不知道异常到底发生了没有。
2)发生异常时,给出友好的消息给用户,但要精确记录错误的所有可能细节,包括发生的时间,和相关方法,类名等。
3)不必每个方法都用try-catch。当特定的异常可能发生时才使用。比如,当你写文件时,处理异常FileIOException.
4)别写太大的 try-catch 模块。如果需要,为每个执行的任务编写单独的 try-catch 模块。 这将帮你找出哪一段代码产生异常,并给用户发出特定的错误消息。
5)只捕捉特定的异常,而不是一般的异常。
好:
void ReadFromFile ( string fileName )
{
try
{
// read from file.
}
catch (FileIOException ex)
{
// log error.
// re-throw exception depending on your case.
throw;
}
}
不好:
void ReadFromFile ( string fileName )
{
try
{
// read from file.
}
catch (Exception ex)
{
// Catching general exception is bad... we will never know whether it
// was a file error or some other error.
// Here you are hiding an exception.
// In this case no one will ever know that an exception happened.
return "";
}
}
不必在所有方法中捕捉一般异常。不管它,让程序崩溃。这将帮助你在开发周期发现大多数的错误。
6)避免利用返回值作为函数的错误代码,应该在程序中使用异常来处理错误。
10 其他
10.1类型转换
1)尽量避免强制类型转换。
2) 如果不得不做类型转换,尽量使用as关键字安全的转换到另一个类型。
Dog dog=new GermanShepherd();
GermanShepherd shepherd=dog as GermanShepherd;
if (shepherd!=null)
{…}
10.2正确性与容错性要求
1)程序首先是正确,其次是优美
2)无法证明你的程序没有错误,因此在编写完一段程序后,应先回头检查。
3)改一个错误时可能产生新的错误,因此在修改前首先考虑对其它程序的影响。
4)对所有的用户输入,必须进行合法性检查。
5)尽量不要比较浮点数的相等,如: 10.0 * 0.1 == 1.0 , 不可靠
6)程序与环境或状态发生关系时,必须主动去处理发生的意外事件,如文件能否逻辑锁定、打印机是否联机等,对于明确的错误,要有明确的容错代码提示用户,在这样不确定的场合都使用Try Throw Catch。
7)单元测试也是编程的一部份,提交联调测试的程序必须通过单元测试。
10.3可重用性要求
1)重复使用的完成相对独立功能的算法或代码应抽象为asp.net服务或类。
2)asp.net服务或类应考虑OO思想,减少外界联系,考虑独立性或封装性。
3)避免让你的代码依赖于运行在某个特定地方的程序集。
10.4其他
1) 不要手动去修改任何机器生成的代码
a) 如果修改了机器生成的代码,修改你的编码方式来适应这个编码标准
b) 尽可能使用partial classes特性,以提高可维护性。(C#2.0新特性)
2)避免在一个程序集中(assembly)中定义多个Main()方法。
3)只把那些绝对需要的方法定义成public,而其它的方法定义成internal。
4)避免使用三元条件操作符。
5)除非为了和其它语言进行互动,否则绝不要使用不安(unsafe)的代码。
6)接口和类中方法和属性的比应该在2:1左右。
7)努力保证一个接口有3~5个成员。
8) 避免在结构中提供方法
a) 参数化的构造函数是鼓励使用的
b) 可以重载运行符
9)当早绑定(early-binding)可能的时候就尽量不要使用迟绑定(late-binding)。
10) 除了在一个构造函数中调用其它的构造函数之外,不要使用this关键字。
//Example of proper use of ‘this’
public class MyClass
{
public MyClass(string message)
{ }
public MyClass():this(“Hello”)
{ }
}
11) 不要使用base关键字访问基类的成员,除非你在调用一个基类构造函数的时候要解决一个子类的名称冲突
//Example of proper use of ‘base’
public class Dog
{
public Dog(string name)
{ }
virtual public void Bark(int howlong)
{ }
}
public class GermanShepherd:Dog
{
public GermanShepherd(string name):base(name)
{ }
override public void Bark(int howLong)
{
base.Bark(howLong)
}
}
12) 生成和构建一个长的字符串时,一定要使用StringBuilder,而不用string。