一、引言html
本文是一套面向C# programmer和C# developer进行开发所应遵循的开发规范程序员
按照此规范来开发C#程序可带来如下益处:编程
代码的编写保持一致性,提升代码的可读性和可维护性,在团队开发一个项目的状况下,程序员之间可代码共享,易于代码的回顾框架
本规范是第一版,只适用于通常状况的通用规范,并不能覆盖全部的状况编辑器
二、文件组织ide
2.1C#源文件布局
类名或文件名要简短,不要超过2000LOC,将代码分割开,使结构清晰。将每一个类放在一个单独的文件中,使用类名来命名文件名(固然扩展名是.cs),这种约定会使你们工做更简单ui
2.2目录设计this
为每个命名空间建立一个目录。(用MyProject/TestSuite/TestTier做为MyProject.TestSuite.TestTier的路径,而不用带点的命名空间名作路径)这样能够更容易地将命名空间映射到目录编码
层次划分。
三、缩进
3.1换行
当一个表达式超过一行时,根据这些通用原则进行处理:
在逗号后换行,在操做符后换行,在高层换行而不要在低层处换行,折行后对齐上一行语句同一层的表达式起始位置。
方法调用换行示例:
longMethodCall(expr1,expr2,expr3,expr4,expr5);
算术表达式换行示例:
推荐:
var = a * b / (c - g + f) +
4 * z;
很差的格式——应避免:
var = a * b / (c - g +
f) + 4 * z;
推荐使用第一种方法,由于是在括号表达式以外折行(高层次折行原则)。注意要用制表符到缩进的位置,而后用用空格到折行的位置。在咱们的例子中是:
> var = a * b / (c - g + f) +
> ......4 * z;
'>'表示是制表符,'.'表示是空格符。(制表符后是空白是用制表符缩进)。一个好的编码习惯就是在所用的编辑器中显示制表符和空格符。
3.2 空白
利用空格进行缩进从未有过统一的标准。一些人喜欢用两个空格,一些人喜欢用四个空格而还有一些人喜欢用八个空格,甚至有的人喜欢用更多的空格。好的作法是用制表符。制表符有一些优势:
· 每一个人均可以设置他们本身喜欢的缩进层级。
· 它仅仅是1个字符而不是2,4,8等等,所以它将减小输入(甚至由于自动缩进,有时你不得不手工设置缩进或取消设置,等等诸如此类的操做)。
· 若是你想增长或减小缩进,能够标记一块,使用Tab增长缩进层级而用Shift-Tab减小缩进层级。这几乎对于任何文本编辑器都是适用的。
这里,咱们定义制表符为标准缩进符。
不要用空格缩进—用制表符!
四、注释
4.1块注释
块注释一般应该是被避免的 。推荐使用///注释做为C#的标准声明。若是但愿用块注释时你应该用如下风格:
/*Line1
*Line2
*Line3
*/
由于这样能够为读者将注释块与代码块区分开。虽然并不提倡使用C风格的单行注释,但你仍然可使用。一旦用这种方式,那么在注释行后应有断行,由于很难看清在同一行中前面有注释的代码
/*blah blah blah */
块注释在极少状况下是有用的。一般块注释用于注释掉大的代码段
4.2单行注释
你应该用//注释风格"注释掉”代码(快捷键,Alt+/),它也能够被用于代码的注释部分
单行注释被用于代码说明时必须缩进到相应的编进层级。注释掉的代码应该放在第一行被注释掉以使注释掉的代码更容易看清
一条经验,注释的长度不该该超过被解释代码的长度太长,由于这表示代码过于复杂,有潜在的bug
4.3文件注释
在.net框架,Microsoft已经介绍了一个基于XML注释的文件。这些文件是包括XML标签的正规的单行的C#注释。他们遵循单行注释的模式:
///<summary>
///This class
///</summary>
多行XML注释遵循这种模式:
///<exception cref="BogusException">
///This exception gets thrown as soon as a
///</exception>
为了被认做是XML注释行,全部的行都必须用三个反斜线开始。标签有如下两类:
文件说明项 格式/参考
第一类包括像<summary><param>or<exception> 的标签。描述一个程序的API元素的这些文档说明项必须写清楚以方便其余程序员。如上面的多行注释示例所示,这些标签一般带有名
称或cref属性。编译器会检查这些属性,因此它们必须是有效正确的。第二类用诸如<code>,<list>or<para>标签,用于控制备注说明的布局。文件能够用‘文件’菜单中的“建立”菜单产生。文件
以html格式产生:
五、声明
5.1每行的声明数
推荐每行只有一个声明,由于它能够方便注释
int level;//indentation level
int size;//size of table
当声明变量时,不要把多个变量或不一样类型的变量放在同一行,例如:
int a, b; //What is 'a'? What does 'b' stand for?
上面的例子也显示了变量名不明显的缺陷。当命名变量时要清晰。
5.2 初始化
局部变量一旦被声明就要初始化。例如:
string name = myObject.Name;
或
int val = time.Hours;
注意:若是你初始化一个dialog,设计使用using语句:
using (OpenFileDialog openFileDialog = new OpenFileDialog()) {
...
}
5.3 类和接口声明
当编写C#类和接口时,应遵循如下格式化规则:
· 在方法名和圆括号“(”开始它的参数列表之间不要使用空格。
· 在声明语句的下一行以大括号"{"标志开始。
· 以"}"结束,经过它自身的缩进与相应的开始标志匹配。
例如:
Class MySample : MyClass, IMyInterface
{
int myInt;
public MySample(int myInt)
{
this.myInt = myInt ;
}
void Inc()
{
++myInt;
}
void EmptyMethod()
{
}
}
对于一个大括号的位置参考10.1部分。
6. 语句
6.1 简单语句
每行都应该只包含一条语句。
6.2 返回语句
一个返回语句不要用最外围圆括号。不用:
return (n * (n + 1) / 2);
用: return n * (n + 1) / 2;
6.3 If, if-else, if else-if else 语句
if, if-else and if else-if else 语句看起来应该像这样:
if (condition) {
DoSomething();
...
}
if (condition) {
DoSomething();
...
} else {
DoSomethingOther();
...
}
if (condition) {
DoSomething();
...
} else if (condition) {
DoSomethingOther();
...
} else {
DoSomethingOtherAgain();
...
}
6.4 for / foreach 语句
一个for语句应该以下形式:
for (int i = 0; i < 5; ++i) {
...
}
或者放置一行(考虑用一个while语句代替)
for (initialization; condition; update) ;
foreach语句应该像下面所示 :
foreach (int i in IntList) {
...
}
注意:在一个循环中,即便只有一个语句一般也用括弧括起来。
6.5 While/do-while 语句
一个while语句应该写成以下形式:
while (condition) {
...
}
一个空while语句应该是如下格式:
while (condition) ;
一个do-while语句应该是以下格式:
do
{
...
} while (condition);
6.6 Switch 语句
一个switch语句应该以下格式:
switch (condition) {
case A:
...
break;
case B:
...
break;
default:
...
break;
}
6.7 Try-catch 语句
一个try-catch statement语句应该遵循如下格式:
try {
...
} catch (Exception) {}
or
try {
...
} catch (Exception e) {
...
}
or
try {
...
} catch (Exception e) {
...
} finally {
...
}
7. 空白
7.1 空行
空行提升可读性。它们分开那些逻辑上自身相关联的代码块。两行空格行应该用于如下之间:
· 一个源文件的逻辑段。
· 类和接口定义(每一个文件只定义一个类或接口以免这种状况)。
一个空格行应该老是被用于如下之间:
· 方法
· 属性
· 一个方法中的局部变量和它的第一条语句
· 一个方法中的逻辑段为了提升可读性。注意空白行必须被缩进由于它们包括一条语句这使得插入这些行更容易。
7.2 内部空格
在一个逗号或一个分号以后应该由一个空格,例如:
TestMethod(a, b, c); 不要用: TestMethod(a,b,c)
或
TestMethod( a, b, c );
单个空格包围操做符(除了像加的一元操做符和逻辑非),例:
a = b; // don't use a=b;
for (int i = 0; i < 10; ++i) // don't use for (int i=0; i<10; ++i)
// or
// for(int i=0;i<10;++i)
7.3 表格格式化
行的一个逻辑块应该做为一个表格被格式化:
string name = "Mr. Ed";
int myValue = 5;
Test aTest = Test.TestYou;
对于表格的格式化用空格而不用制表符由于在某些制表符缩进设置会使表格格式化看起来是很奇怪。
8. 命名习惯
8.1 大写格式
8.1.1 Pascal Casing
习惯大写每一个单词的第一个字母(就像在TestCounter)。
8.1.2 Camel Casing
习惯除了第一个单词外大写每一个单词的第一个字母例如testCounter。
8.1.3 全大写状况
对于只有一两个字符缩写组成的标识符才用全大写的状况。有三个或更多个字符组成的标识符应该用Pascal状况代替。例如:
public class Math
{
public const PI = ...
public const E = ...
public const feigenBaumNumber = ...
}
8.2. 命名指导方针
一般根据指导方针在名字和命名内用低线字符对Hungarian 符号来讲被认为是坏习惯。
Hungarian 符号是一组应用于命名来映射变量类型的前缀和后缀。这种命名风格在早期的Windows程序中被普遍应用,但如今被取消了至少不提倡了。若是你遵循这个指南用Hungarian 符号是不容许的。
但要记住一个好的变量名描述了语义而不失类型。
对于这个规则有个例外就是GUI编码。包括像按钮(buttton)的GUI元素,全部领域和变量名都应该带有它们类型名的后缀不是缩写。例如:
System.Windows.Forms.Button cancelButton;
System.Windows.Forms.TextBox nameTextBox;
8.2.1 类命名指导方针
· 类命名必须是名词或名词短语。
· UsePascal 状况参考8.1.1
· 不要用任何类前缀
8.2.2 接口命名指导方针Guidelines
· 用能够描述行为的名词或名词短语或形容词命名接口。(例如IComponent 或 IEnumberable)
· 用Pascal状况(参考8.1.1)
· 用I做为名字的前缀,它应该紧跟一个大写字母(接口名的第一个字母)
8.2.3 枚举命名指导方针
· 用Pascal状况命名枚举值名字和类型名字
· 枚举类型和枚举值不要前缀
· 对于枚举用单一名字
· 对于位领域用复数名字
8.2.4 只读和常量命名
· 用名词,名词短语或名词的缩写命名静态领域
· 使用Pascal 状况(参考8.1.1)
8.2.5 参数/很是量领域命名
· 必定要用描述性名字,应该可以足够表现变量的意义和它的类型。但一个好的名字应该基于参数的意义。
· 使用Camel状况(参考8.1.2)
8.2.6 变量命名
· 计数变量当用在琐碎的计数循环式更适宜叫i, j, k, l, m, n。(参考10.2例如对全局计数的更智能命名等等)—
· 使用Camel状况(参考8.1.2)
8.2.7 方法命名
· 用动词或动词短语命名方法。
· 使用Pascal(参考8.1.2)
8.2.8 属性命名
· 用名词或名词短语命名属性
· 使用Pascal 状况(参考8.1.2)
· 考虑用与其类型相同的名字命名一个属性
8.2.9 事件命名
· 用事件处理器后缀命名事件处理器
· 用sender 和 e命名两个参数
· 使用Pascal状况(参考8.1.1)
· 用EventArgs 后缀命名事件参数
· 用如今和过去时态命名有前缀和复制概念的事件名字。
· 考虑用一个动词命名事件。
8.2.10 大写总结
Type |
Case |
Notes |
Class / Struct |
Pascal Casing |
|
Interface |
Pascal Casing |
Starts with I |
Enum values |
Pascal Casing |
|
Enum type |
Pascal Casing |
|
Events |
Pascal Casing |
|
Exception class |
Pascal Casing |
End with Exception |
public Fields |
Pascal Casing |
|
Methods |
Pascal Casing |
|
Namespace |
Pascal Casing |
|
Property |
Pascal Casing |
|
Protected/private Fields |
Camel Casing |
|
Parameters |
Camel Casing |
|
9. 编程习惯
9.1 可见性
不要任何公共实例或类变量,让它们为私有的。对于私有成员最好不用“private”做修饰语什么都不写。私有是默认状况,每一个C#程序员都应该知道这一点。
用属性代替。你能够用公共静态(或常量)对于这个规则是以例外,带它不该该是规则。
9.2 没有“幻”数
不要用幻数,也就是在源代码中直接用常数值。替代这些后者以防变化(比方说,你的应用程序能够处理3540用户代替427你的代码在50行中经过分散25000LOC)是错误和没有收益的。声明一个带有数的常量来代替:
public class MyMath
{
public const double PI = 3.14159...
}
10. 编码举例
10.1 Brace placement example
namespace ShowMeTheBracket
{
public enum Test {
TestMe,
TestYou
}
public class TestMeClass
{
Test test;
public Test Test {
get {
return test;
}
set {
test = value;
}
}
void DoSomething()
{
if (test == Test.TestMe) {
//...stuff gets done
} else {
//...other stuff gets done
}
}
}
}
括弧应该在如下状况以后以新行开始:
· 命名空间声明(注意这在0.3版本中是新添的与0.2版本不一样)
· 类/接口/结构声明
· 方法声明
10.2 变量命名举例
代替:
for (int i = 1; i < num; ++i) {
meetsCriteria[i] = true;
}
for (int i = 2; i < num / 2; ++i) {
int j = i + i;
while (j <= num) {
meetsCriteria[j] = false;
j += i;
}
}
for (int i = 0; i < num; ++i) {
if (meetsCriteria[i]) {
Console.WriteLine(i + " meets criteria");
}
}
try intelligent naming :
for (int primeCandidate = 1; primeCandidate < num; ++primeCandidate)
{
isPrime[primeCandidate] = true;
}
for (int factor = 2; factor < num / 2; ++factor) {
int factorableNumber = factor + factor;
while (factorableNumber <= num) {
isPrime[factorableNumber] = false;
factorableNumber += factor;
}
}
for (int primeCandidate = 0; primeCandidate < num; ++primeCandidate)
{
if (isPrime[primeCandidate]) {
Console.WriteLine(primeCandidate + " is prime.");
}
}
注意:索引变量一般叫i, j, k 等等。但Note: Indexer variables generally should be called i, j, k etc. But 万一像这样,使得从新考虑这个原则更有意义。通常来讲,当同一个计数器或索引器被重用,给它们有意义的名字。