C#代码规范 程序员必备的秘笈
1、引言
本文是一套面向C# programmer和C# developer进行开发所应遵循的开发规范
按照此规范来开发C#程序可带来以下益处:
代码的编写保持一致性,提高代码的可读性和可维护性,在团队开发一个项目的情况下,程序员之间可代码共享,易于代码的回顾
本规范是初版,只适用于一般情况的通用规范,并不能覆盖所有的情况
2、文件组织
2.1C#源文件
类名或文件名要简短,不要超过2000LOC,将代码分割开,使结构清晰。将每个类放在一个单独的文件中,使用类名来命名文件名(当然扩展名是.cs),这种约定会使大家工作更简单
2.2目录设计
为每一个命名空间创建一个目录。(用MyProject/TestSuite/TestTier作为MyProject.TestSuite.TestTier的路径,而不用带点的命名空间名做路径)这样可以更容易地将命名空间映射到目录
层次划分。
3、缩进
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、注释
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、声明
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 万一像这样,使得重新考虑这个原则更有意义。一般来说,当同一个计数器或索引器被重用,给它们有意义的名字。
C#代码规范 程序员必备的秘笈的更多相关文章
- 代码自动生成工具MyGeneration之一(程序员必备工具)
代码自动生成工具MyGeneration之一(程序员必备工具) 转 分类: C#2008-08-06 18:12 16064人阅读 评论(12) 收藏 举报 工具数据库相关数据库stringbrows ...
- Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!
Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器! http://www.iplaysoft.com/sublimetext.html 代码编辑器或者文本编辑器,对于程序员来说, ...
- Android java程序员必备技能,集合与数组中遍历元素,增强for循环的使用详解及代码
Android java程序员必备技能,集合与数组中遍历元素, 增强for循环的使用详解及代码 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 For ...
- <转载> 优秀程序员必备的23条好习惯
转自 优秀程序员必备的23条好习惯 编程是一项聪明人玩的游戏,它既是对智力的考验,也是对习惯的考验,智力的好坏取决于父母的基因,人们无从左右,但习惯的好坏却是可以不断培养.一项由美国芝加哥大学国家研究 ...
- 「编程羽录」上线,程序员必备的这些技能你能get到嘛?
大家好,我是小羽. 好久不见,给大家带来个好消息,小羽的全新专题「编程羽录」系列正式上新,主要是介绍一些关于面试题和经验总结的文章. 会为大家提供一些技术栈之外,程序员还需要的其他方面硬核知识,做到全 ...
- Java程序员必备的 15框开发工具
15款Java程序员必备的开发工具 如果你是一名Web开发人员,那么用膝盖想也知道你的职业生涯大部分将使用Java而度过.这是一款商业级的编程语言,我们没有办法不接触它. 对于Java,有两种截然不同 ...
- Java 程序员必备的 15 个框架,前 3 个地位无可动摇!
Java 程序员方向太多,且不说移动开发.大数据.区块链.人工智能这些,大部分 Java 程序员都是 Java Web/后端开发.那作为一名 Java Web 开发程序员必须需要熟悉哪些框架呢? 今天 ...
- 十大PHP程序员必备工具
十大PHP程序员必备工具 1.Notepad++ 总结来说就是小而精,7.4版本的软件包只有2.9M,比一般的IDE小数十倍,但是Notepad++的功能确是很全面的,代码高亮,语法折叠,宏功能,内置 ...
- 程序员必备技能之Markdown
Markdown介绍 Markdown是一种纯文本格式的标记语言,比HTML更简单,通过一些简单的语法标记,就可以让文本简洁好看. Markdown已经是程序员一项必备技能了,代码块.流程图.序列图. ...
随机推荐
- Kmeans聚类算法分析(转帖)
原帖地址:http://www.opencvchina.com/thread-749-1-1.html k-means是一种聚类算法,这种算法是依赖于点的邻域来决定哪些点应该分在一个组中. ...
- 检测 USB 设备拨插的 C# 类库:USBClassLibrary
这是采用C#开发的一个USB库,使您可以管理USB设备的连接和分离事件,探测自己的设备.可以运行在Windows XP和Windows7 64位系统下. 01 private void USBPort ...
- c++call back
#include "stdafx.h" struct A; typedef void(A::*MemFuncPtr) (int* e); class A { int a; }; c ...
- IOS中的手势详解
1.点击 UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selecto ...
- 2015年末分享:利用RS修改用户密码
马上就要2016农历新年了,送点什么给大家呢?我觉得还是分享点技术吧.前不久用户在抱怨为什么登录Cognos Connection的密码不能让我们自己改?相信Cognos开发的很多人知道,Cognos ...
- Untracked Files Prevent Checkout move or commit them before checkout
点开View Files... 查看里面的文件名称,在项目的.idea文件夹中删掉ViewFiles显示的文件夹名称就好
- 一个简单RPC框架是怎样炼成的(IV)——实现RPC消息的编解码
之前我们制定了一个非常easy的RPC消息 的格式,可是还遗留了两个问题,上一篇解决掉了一个.还留下一个 我们并没有实现对应的encode和decode方法,没有基于能够跨设备的字符串传输,而是直接的 ...
- IE11下javascript报堆栈溢出问题的解决
在IE11浏览器下,使用日期函数里面的toLocaleDateString()会报堆栈溢出 不知道是不是跟我的其他相关代码有关,还是就是这个toLocaleDateString()在IE11确实不太一 ...
- JavsScript 之 求时间差
var dateStart = new Date(); //开始时间var dateEnd = new Date(); //结束时间 var timePeriod = dateEnd.getTime( ...
- OpenERP 在context中写自己的部门ID
使用OpenERP自定义模块开发的时候,你会发现,有一个uid(当前登录用户id)特别好用,不管是在xml的domain 条件表达式中,还是在类中,都能很方便的使用uid.有一段时间就一直在琢磨,这个 ...