1.简介
本规范为一套编写高效可靠的c#代码的标准,约定和指南。它可以安全可靠的软件工程的原则为基础,使代码易于理解,维护和增强,提高生产效率。同时,将带来更大的一致性,使软件开发团队的效率明显提高。
2.适用范围
本规范适用于公司所有的C#源代码,为详细设计,代码编写和代码审核提供参考和依据。
3.文体
在规范中的建议分为四种:要,建议,避免,不要,表示需要遵循级别。文档中会以粗体表示。对于遵循的规范,前面以“0”来表示,对不好的做法前面会以“‘” 来表示。
要:描述必须遵循的规范。例如:
异常类要以"Exception “ 作为后缀;
建议:描述在一般情况下应该遵循的规范,但如果完全理解规范背后的道理,并有很好的理由不遵循它时,也不畏惧打破常规。例如:
强制类型转换时,在类型和变量之间建议加一个空格。
不要:描述一些几乎绝对绝不应该违反的规范。例如:
每个函数有效代码(不包括注释和空行) 长度不要超过50行。
避免:与建议相对,一般情况下应该遵循,但又很好理由时也可以打破。例如:
避免块内的变量和它外部的变量名相同。
4.代码组织与风格
4.1 Tab
要使一个Tab为4个空格长
4.2 缩进
要使一个代码块内的代码都统一缩进一个Tab长度。
4.3空行
建议适当地增加空行,来增加代码的可读性。
在类,接口以及彼此之间要有两行空行:
在下列情况之间要有一行空行:
方法之间;
局部变量和它后边的语句之间;
方法内的功能逻辑部分;
4.4函数长度
每个函数有效代码(不包括注释和空行) 长度不要超过50 行。
4.5 “{”,“}”
开括号“}" 要放在块的所有者的下一行,单起一行;
比括号“}" 要单独放在代码块的最后一行,单起一行。
4.6 行宽
每行代码和注释不要超过70个字符或屏幕的宽度,如果超过则换行,换行后的代码应该缩进一个Tab。
4.7 空格
括号和它里面的字符之间不要出现空格。括号应该和他前边的关键词留有空格,
如:while(true){};
但是方法名和左括号之间不要有空格。
参数之间的逗号要加一空格。如:method1(int i1, int i2)
for语句里的表达式之间要加一个空格如:for (exper1;exper2;exper3)
二元操作符和操作数之间要用空格隔开。如:i + c;
5.1 注释的基本约定
注释应该增加代码的清晰度;
保持注释的简介,不是任何代码都需要注释,过多的注释反而会影响代码的可读性。
注释不要包括其他的特殊字符。
建议先写注释,后写代码,注释和代码一起完成
如果语句块代码太长,嵌套太多,则在其结束”}“要加上注释,标志对应的开始语句。
如果分支条件逻辑比较复杂,也要加上注释。
5.2 注释类型
5.2.1 块注释
主要用来描述文件,类,方法,算法等,放在所描述对象的前边。具体格式以IDE编辑器输入“///"自动生成的格式为准,另外再附加我们自定义的格式,如下所列:
/// <Remark>作者,创建日,修改日期〈/Remark>
5.2.2 行注释
主要用在方法内部,对代码,变量,流程等进行说明。整个注释占据一行。
5.2.3尾随注释
与行注释功能相似,放在代码的同行,但是要与代码之间有足够的空间,便于分清。列:
int m = 4 ; // 注释
如果一个程序块内有多个尾随注释,每个注释的缩进要保持一致。
5.3 注释哪些部分
项目 |
注释哪些部分 |
参数 |
参数用来做什么 任何约束或前提条件 |
字段/属性 |
字段描述 |
类 |
类的目的 已知的问题 类的开发/维护历史 |
接口 |
目的 它应如何被使用以及如何不被使用 |
局部变量 |
用处/目的 |
成员函数注释 |
成员函数做什么以及它为什么做这个 哪些参数必须传递给一个成员函数 成员函数返回什么 已知的问题 任何由某个成员函数抛出的异常 成员函数是如何改变对象的 包含任何修改代码的历史 如何在适当情况下调用成员函数的例子适用的前提条件和后置条件 |
成员函数内部注释 |
控制结构 代码做了些什么以及为什么这样做 局部变量 难或复杂的代码 处理顺序 |
5.4 程序修改注释
新增代码行的前后要有注释行说明,对格式不做要求,但必须包含作者,新增时间,新增目的。在新增代码的最后必须加上结束标志;
删除代码行的前后要用注释行说明,删除代码用注释原有代码的方法。注释方法和内容同新增;删除的代码建议用#region XXX #endregion 代码段折叠,保持代码文件干净整洁
修改代码行建议以先删除代码行后再新增代码行的方式进行,注释方法和内容同新增;
6.命名
6.1命名的基本约定
要使用可以准确说明变量/字段/类的完整的英文描述符,如firstName。对一些作用显而易见的变量可以采用简单的命名,如在循环里的递增(减)变量就可以被命名为“i”。
要尽量采用项目所涉及领域的术语。
要采用大小写混合,提高名字的可读性。为区分一个标识符中的多个单词,把标示符中的每个单词的首字母大写。不采用下划线作分隔字符的写法。有两种适合的书写方法,适用于不同类型的标示符:
camelCasing:表示符的第一个单词的字母小写;
下表描述了不同类型标示符的大小写规则 :
标识符 |
大小写 |
示例 |
命名空间 |
Pascal |
namespace Com.Techstar.ProductionCenter |
类型 |
Pascal |
public class DevsList |
接口 |
Pascal |
public interface ITableModel |
方法 |
Pascal |
public void UpdateData() |
属性 |
Pascal |
Public int Length{…} |
事件 |
Pascal |
public event EventHandler Changed; |
私有字段 |
Camel |
private string fieldName; |
非私有字段 |
Pascal |
public string FieldName; |
枚举值 |
Pascal |
FileMode{Append} |
参数 |
Camel |
public void UpdateData(string fieldName) |
局部变量 |
Camel |
string fieldName; |
避免使用缩写。
避免使用长名字(最好不超过15个字母)。
避免使用相似或者仅在大小写上有区别的名字。
6.2 各种标示符的命名约定
公司域名(Techstar) + 项目名称 +模块名称(可选) ,例如:
中心系统程序集:Techstar.ProductionCenter;
中心系统业务逻辑程序集:Techstar.ProductionCenter.Business;
6.2.2 命名空间命名
采用和程序集命名相同的方式:公司域名(Techstar)+项目名称+模块名称。
中心系统:Techstar.ProductionCenter;
中心系统下的用户控件:Techstar.ProductionCenter.UserControl;
中心系统业务逻辑:Techstar.ProductionCenter.Business;
中心系统的数据访问:Techstar.ProductionCenter.Data;
6.2.3 类和接口命名
类的名字要用名词
避免使用单词的缩写,除非它的缩写已经广为人知,如HTTP.
接口的名字要以字母I开头。保证对接口的标准实现名字只相差一个“I”前缀,
例如对IComponent的标准实现为Component;
泛型类型参数的命名:命名要为T或者以T开头的描述性名字,例如:
public class List<T>
public class Myclass<TSession>
对同一项目的不同命名空间中的类,命名避免重复。避免引用时的冲突和混淆;
6.2.4 方法命名
第一个单词一般是动词
如果方法返回一个成员变量的值,方法名一般为Get+成员变量名,若返回的值是bool变量,一般以Is作为前缀。另外,如果必要,考虑用属性来替代方法,具体建议减10.1.2节;
如果方法修改一个成员变量的值,方法名一般为:Set + 成员变量名。同上,考虑用属性来代替方法;
6.2.5 变量命名
按照使用范围来分,我们代码中的变量基本上有以下几种类型,类的公有变量;
类的私有变量(受保护);方法的参数变量;方法内部使用的局部变量。
这些变量的命名规则基本相同,见标示符大小对照表。区别如下:
i. 类的公有变量按通常的方式命名,无特殊要求;
ii.类的私有变量采用两种方式均可:采用加“m”前缀,例如mWorkerName
iii.方法的参数变量采用camalString,例如workerName;
iv.方法内部的局部变量采用camalString,例如workerName;
不要用_或&作为第一个字母;
尽量要使用短而具有意义的单词;
单字符的变量名一般只用于生命期非常短暂的变量。i,j,k,m,n,一般用于integer;c,d,e一般用于characters;s用于string
如果变量是集合,则变量名要用复数。例如表格的行数,命d名应为:RowsCount;
命名组件要采用匈牙利命名法,所有前缀均应遵循同一个组件名称缩写列表
6.3 组件名称缩写列表
缩写的基本原则是取组件类名个单词的第一个字母,如果只有一个单词,则去掉其中的元音,留下辅音,缩写全部为小写。
Data Control
类 型 |
前 缀 |
示 例 |
AccessDataSource |
ads |
adsPubs |
DataList |
dlst |
dlstTitles |
DetailView |
dvw |
dvwTitles |
FormView |
fvw |
fvwFonts |
GridView |
gvw |
gvwCity |
ObjectDataSource |
ods |
odsMenus |
Repeater |
rpt |
rptQueryResults |
ReportViewer |
rvw |
rvwRecord |
SiteMapDataSource |
smds |
smdsSite |
SqlDataSource |
sds |
sdsBooks |
XmlDataSource |
xds |
xdsTitles |
Validation Control
类 型 |
前 缀 |
示 例 |
CompareValidator |
valc |
valcValidAge |
CustomValidator |
valx |
valxDBCheck |
RangeValidator |
valg |
valgAge |
RegularExpressionValidator |
vale |
valeEmail |
RequiredFieldValidator |
valr |
valrFirstName |
ValidationSummary |
vals |
valsFormErrors |
Navigation Control
类 型 |
前 缀 |
示 例 |
Menu |
mnu |
mnuUser1 |
SiteMapPath |
smp |
smpSite1 |
TreeView |
trvw |
trvwMenu |
Login Control
类 型 |
前 缀 |
示 例 |
ChangePassword |
cpwd |
cpwdUser1 |
CreateUserWizard |
cuw |
cuwLogin |
Login |
log |
logCenter |
LoginName |
logn |
lognUser |
LoginStatus |
logs |
logsUser |
LoginView |
logv |
logvUser |
PasswordRecovery |
pwdr |
pwdrUser |
WebParts Control
类 型 |
前 缀 |
示 例 |
AppearanceEditorPart |
paed |
paedPart1 |
BehaviorEditorPart |
pbed |
pbedPart2 |
CatalogZone |
zca |
zcatCity |
ConnectionsZone |
zcon |
zconDataBase |
DeclarativeCatalogPart |
pdca |
pdcaPart1 |
EditorZone |
zed |
zedNews |
ImportCatalogPart |
pica |
picaPart |
LayoutEditorPart |
pled |
pledNews |
PageCatalogPart |
ppca |
ppcaMail |
PropertyGridEditorPart |
ppge |
ppgeServer |
ProxyWebPartManager |
mpwp |
mpwpWeb |
WebPartManager |
mwp |
mwpSite1 |
WebPartZone |
zwp |
zwpSite2 |
基本数据类型
数据类型 |
数据类型简写 |
标准命名举例 |
Array |
arr |
arrShoppingList |
Boolean |
bln |
blnIsPostBack |
Byte |
byt |
bytPixelValue |
Char |
chr |
chrDelimiter |
DateTime |
dtm |
dtmStartDate |
Decimal |
dec |
decAverageHeight |
Double |
dbl |
dblSizeofUniverse |
Integer |
int |
intRowCounter |
Long |
lng |
lngBillGatesIncome |
Object |
obj |
objReturnValue |
Short |
shr |
shrAverage |
Single |
sng |
sngMaximum |
String |
str |
strFirstName |
ADO.NET 命名规范
数据类型 |
数据类型简写 |
标准命名举例 |
Connection |
con |
conNorthwind |
Command |
cmd |
cmdReturnProducts |
Parameter |
parm |
parmProductID |
DataAdapter |
dad |
dadProducts |
DataReader |
dtr |
dtrProducts |
DataSet |
dst |
dstNorthWind |
DataTable |
dtbl |
dtblProduct |
DataRow |
drow |
drowRow98 |
DataColumn |
dcol |
dcolProductID |
DataRelation |
drel |
drelMasterDetail |
DataView |
dvw |
dvwFilteredProducts |
WinForm Control 命名规范
数据类型 |
数据类型简写 |
标准命名举例 |
Label |
lbl |
lblMessage |
LinkLabel |
llbl |
llblToday |
Button |
btn |
btnSave |
TextBox |
txt |
txtName |
MainMenu |
mmnu |
mmnuFile |
CheckBox |
chk |
chkStock |
RadioButton |
rbtn |
rbtnSelected |
GroupBox |
gbx |
gbxMain |
PictureBox |
pic |
picImage |
Panel |
pnl |
pnlBody |
DataGrid |
dgrd |
dgrdView |
ListBox |
lst |
lstProducts |
CheckedListBox |
clst |
clstChecked |
ComboBox |
cbo |
cboMenu |
ListView |
lvw |
lvwBrowser |
TreeView |
tvw |
tvwType |
TabControl |
tctl |
tctlSelected |
DateTimePicker |
dtp |
dtpStartDate |
HscrollBar |
hsb |
hsbImage |
VscrollBar |
vsb |
vsbImage |
Timer |
tmr |
tmrCount |
ImageList |
ilst |
ilstImage |
ToolBar |
tlb |
tlbManage |
StatusBar |
stb |
stbFootPrint |
OpenFileDialog |
odlg |
odlgFile |
SaveFileDialog |
sdlg |
sdlgSave |
FoldBrowserDialog |
fbdlg |
fgdlgBrowser |
FontDialog |
fdlg |
fdlgFoot |
ColorDialog |
cdlg |
cdlgColor |
PrintDialog |
pdlg |
pdlgPrint |
WebControl 命名规范
类 型 |
前 缀 |
示 例 |
Adrotator |
adrt |
adrtTopAd |
BulletedList |
blst |
blstCity |
Button |
btn |
btnSubmit |
Calendar |
cal |
calMettingDates |
CheckBox |
chk |
chkBlue |
CheckBoxList |
chkl |
chklFavColors |
CompareValidator |
valc |
valcValidAge |
CustomValidator |
valx |
valxDBCheck |
DropDownList |
drop |
dropCountries |
DataGrid |
dgrd |
dgrdTitles |
DataList |
dlst |
dlstTitles |
RangeValidator |
valg |
valgAge |
FileUpLoad |
fup |
fupImage |
HiddenField |
hfld |
hfldName |
HyperLink |
hlk |
hlkDetails |
Image |
img |
imgAuntBetty |
ImageButton |
ibtn |
ibtnSubmit |
ImageMap |
imap |
imapSite |
Label |
lbl |
lblResults |
LinkButton |
lbtn |
lbtnSubmit |
ListBox |
lst |
lstCountries |
Literal |
ltl |
ltlTitle |
Localize |
loc |
locChina |
MultiView |
mvw |
mvwForm1 |
Panel |
pnl |
pnlForm2 |
PlaceHolder |
plh |
plhFormContents |
RadioButton |
rad |
radFemale |
RadioButtonList |
radl |
radlGender |
RegularExpression |
vale |
valeEmail_Validator |
Repeater |
rpt |
rptQueryResults |
RequiredFieldValidator |
valr |
valrFirstName |
SubStitution |
subs |
subsTime |
TextBox |
txt |
txtFirstName |
Table |
tbl |
tblCountryCodes |
TableCell |
tblc |
tblcGermany |
TableRow |
tblr |
tblrCountry |
ValidationSummary |
vals |
valsFormErrors |
View |
vw |
vwCity |
Wizard |
wiz |
wizRegister |
Xml |
xml |
xmlBooks |
7.声明
每行要只有一个声明,如果是声明i,j,k之类的简单变量可以放在一行;
除了for循环外,声明要放在块的最开始部分。for循环中的变量声明可以放在for语句中。
如:for(int i =0 ; I <10;I++)
避免块内部的变量与它外部的变量名相同。
8.表达式和语句
每行建议只有一条语句。
if-else,if-else if 语句,任何情况下都应该有“{”“}”格式如下。
if( condition)
{
statements;
}
else if(condition)
{
statements;
}
9.类型设计规范
要确保每个类型由一组定义明确,相互关联的成员组成而不是仅仅一些无关功能的随机集合;
9.1 类型和命名空间
要用命名空间把类型组织成相关域的层次结构。例如:
界面层:Techstar.ProductionCenter;
业务逻辑层:Techstar.ProductionCenter.Business;
数据访问层:Techstar.ProductionCenter.Data;
避免过深的命名空间;
避免太多的命名空间;
9.2 类型和接口的选择
要优先采用类而不是接口。
接口的缺点在于语义变化时改变困难。注意接口并不是协定,把协定和实现区分开并非一定用接口实现,用基类和抽象类同样可以表达;
建议使用抽象类而不是接口来接触协定与实现间的偶合;
要定义接口,来实现类似多重继承的效果;
精心定义接口的标志是一个接口只做一件事情。关键是接口的协定需要保持不变,如果一个接口包含太多功能,那么这个胖接口产生变化的机会就会大得多。
9.3 抽象类设计:
不要在抽象类中定义公有的或内部受保护的构造函数。因为抽象类无法实例化,所以这种设计会误导用户;
要为抽象类定义受保护的构造函数或内部构造函数;
9.4静态类设计
静态类时一个只包含静态成员的类,它提供了一种纯面向对象设计和简单性之间的一个权衡,广泛用来提供类似于全局变量或一些通用功能。
要少用静态类。静态类应该仅用作辅助类;
避免把静态类当做杂物箱。每个静态类都应该有其明确目的;
不要在静态类中声明或覆盖实例成员;
9.5枚举设计
要用枚举来加强那些表示值得集合的参数,属性及返回值的类型性;
要优先使用枚举而不是静态常量。例如:
public enum Color
{
Red,
Greed,
Blue
}
不要把枚举用于开放的场合,例如操作系统的版本,朋友的名字等;
枚举最后一个只不要加逗号;