C#编码规范
术语
Pascal 大小写:将标识符的首字母和后面连接的每个单词的首字母都大写。可以对三字符或更多字符的标识符使用Pascal 大小写。例如:BackColor
Camel 大小写:标识符的首字母小写,而每个后面连接的单词的首字母都大写。例如: backColor
文件命名
文件名遵从Pascal命名法,无特殊情况,扩展名小写。
文件开始包含类似以下注释说明
/******************************************** // 文件名: // 文件功能描述: // 创建人: // 创建时间: // 描述: // 修改人: // 修改时间: // 修改描述: //******************************************/
文件功能描述着重于描述文件功能与说明,详情应在类的注释中描述。
一天内有多个修改只需做做一个修改标识,在所有的代码修改处加上修改标识的注释。
代码外观
列宽
代码列宽控制在100字符左右。
代码换行,换行后的代码应该缩进一个Tab。
换行
当表达式超出或即将超出规定的列宽,遵循以下规则进行换行
在逗号后换行。
在操作符前换行。
规则1优先于规则2。
当以上规则会导致代码混乱的时候自己采取更灵活的换行规则。
缩进
缩进应该是每行一个Tab(4个空格),不要在代码中使用Tab字符。
空行
在以下情况下使用两个空行
接口和类的定义之间。
枚举和类的定义之间。
类与类的定义之间。
在以下情况下使用一个空行
方法与方法、属性与属性之间。
方法中变量声明与语句之间。
方法与方法之间。
方法中不同的逻辑块之间。
方法中的返回语句与其他的语句之间。
属性与方法、属性与字段、方法与字段之间。
注释与它注释的语句间无空行,但与其他的语句空一行。
空格
在以下情况中要使用到空格
关键字和左括号(应该用空格隔开。
在方法名和左括号 ( 之间不要使用空格。
多个参数用逗号隔开,每个逗号后都应加一个空格。
除了 . 之外,所有的二元操作符都应用空格与它们的操作数隔开。
一元操作符、++及--与操作数间不需要空格。
语句中的表达式之间用空格隔开。如for (expr1; expr2; expr3)
括号
左括号(不要紧靠关键字,中间用一个空格隔开。
左括号(与方法名之间不要添加任何空格。
没有必要的话不要在返回语句中使用()。
花括号
左花括号{放于关键字或方法名的下一行并与之对齐。
左花括号{要与相应的右花括号 }对齐。
通常情况下左花括号{单独成行,不与任何语句并列一行。
if、while、do、for语句后一定要使用{},即使{}号中为空或只有一条语句。
右花括号} 后加一个注释以便于方便的找到与之相应的{。
块语句
将大的复杂代码节分为较小的、易于理解的模块。
当一行被分为几行时,将运算符放在行的末尾,标识行是不完整的。
在代码中垂直对齐左括号和右括号。
if (x == 0)
{
}
不允许以下情况:
if (x == 0) {
}
if (x == 0){ xxx;}
程序注释
注释原则
注释应该是解释为什么和做什么,而不是介绍是什么。
修改代码时,总是使代码周围的注释保持最新。
变量声明时,使用行尾注释是合适的;其他情况下,使用单行注释。
避免杂乱的注释,如一整行星号。而是应该使用空白将注释同代码分开。
在部署发布之前,移除所有临时或无关的注释,避免维护工作中产生混乱。
如果需要用注释来解释复杂的代码节,先检查代码是否应该重写。
在编写注释时使用完整的句子。注释应该阐明代码,而不应该增加多义性。
避免多余的或不适当的注释。
注释代码中不十分明显的任何内容。
为了防止问题反复出现,对错误和解决方法总是使用注释。
对由循环和逻辑分支组成的代码使用注释。
使用具有一致的风格和语言来构造注释。
用空白将注释同注释分隔符分开。
新增代码行的前后要有注释行说明,对具体格式不作要求,但必须包含作者,新增时间,新增目的。在新增代码的最后必须加上结束标志;
善于运用#region,#endregion。
单行注释
用于方法内的代码注释。如变量的声明、代码或代码段的解释。示例:
// 注释语句
private int number;
方法内变量的声明或花括号后的注释,示例:
// always true
if ( 1 == 1)
{
statement;
} // always true
多行注释:
该类注释用于说明一段代码的逻辑、运算步骤、注意事项等需要详细说明的内容。
/* statement description
* statement description
* statement description */
statement;
文档注释
.Net预定义Xml标签来标记对象说明,在声明接口、类、方法、属性、字段都应该使用该类注释。
/// <summary>
/// 方法描述
/// </summary>
/// <param name=key>参数说明</param>
/// <returns>返回值说明</returns>
public static void Method(string key)
{
return ;
}
类注释
模块开始尽量以以下形式书写模块注释:
/******************************************** // 类名: // 功能描述: // 创建人: // 创建时间: // 描述: // 修改人: // 修改时间: // 修改描述: //******************************************/
注意:类的修改应该在注释中添加修改记录,且记录累加。
属性注释
在类的属性必须以以下格式编写属性注释:
/// <summary>
///属性说明
/// </summary>
方法注释
在类的方法声明前必须以以下格式编写注释:
/// </summary>
/// 函数的作用
/// <param name=<参数名称>><参数说明></param>
/// <returns><返回值的说明,该说明必须明确说明返回的值代表什么含义> </returns>
///<exception>异常类型、异常结果说明(为什么产生此异常)</exception>
对象声明
变量声明
建议一行只作一个声明。示例:
int level; //推荐
int size; //推荐
int x, y; //不推荐
在变量声明时就对其做初始化。
变量声明置于块的开始处,不要总是在第一次使用它们的地方做声明。例外:
for (int i = 0; i < len; i++) { }
避免不同层次间的变量重名
类、接口声明
在方法名与其后的左括号间没有任何空格。
左花括号{出现在声明的下行并与之对齐,单独成行。
方法间用一个空行隔开。
字段声明
不要使用是 public 或 protected 的字段。
如果需要将字段公开,请使用属性
代码规范
命名规范
命名由字母、数字和_组成。命名是为了帮助人们阅读。
避免使用系统保留字。
应选择正确的名称,能够表明功能或定义目的。
在编程上通过命名可以将各项明确的区分开来。
避免容易被主观解释的难懂的名称,避免歧义。
只要合适,在变量名的末尾或开头加计算限定符。
在一组相关变量的命名中使用互补对,如 min/max、begin/end 和 open/close。
布尔变量名应该包含 Is,这意味着 Yes/No 或 True/False 值。
在命名状态变量时,避免使用诸如单纯 Flag或Status 的术语。
大小写规则
大写
标识符中的首字母大写,仅对于由两个或者更少字母组成的标识符使用该约定。示例:
System.IO System.Web.UI
下表汇总了大写规则,并提供了不同类型的标识符的示例。
标识符 |
大小写 |
示例 |
类 |
Pascal |
AppDomain |
枚举类型 |
Pascal |
ErrorLevel |
枚举值 |
Pascal |
FatalError |
事件 |
Pascal |
ValueChange |
异常类 |
Pascal |
WebException 总是Exception后缀结尾。 |
静态字段 |
Pascal |
RedValue |
接口 |
Pascal |
IDisposable总是I前缀开始。 |
方法 |
Pascal |
ToString |
命名空间 |
Pascal |
System.Drawing |
属性 |
Pascal |
BackColor |
公共实例字段 |
Pascal |
RedValue属性优于使用公共实例字段。 |
受保护的实例字段 |
Camel |
redValue属性优于使用受保护的实例字段。 |
私有的实例字段 |
Camel |
redValue |
参数 |
Camel |
typeName |
方法内的变量 |
Camel |
backColor |
缩写
不要将缩写或缩略形式用作标识符名称的组成部分。
不要使用计算机领域中未被普遍接受的缩写。
在适当的时候,使用众所周知的缩写替换冗长的词组名称。例如UI或OLAP。
使用缩写时,对于超过两个字符长度的缩写请使用 Pascal 大小写或 Camel 大小写,但应当大写仅有两个字符的缩写,如System.IO而不是 System.Io。
不要在标识符或参数名称中使用缩写。
命名空间
命名空间使用公司名.项目名称,后续可添加按技术名称和功能、模块名称。
命名空间和类不能重名。
类
用名词或名词短语命名类。
使用全称避免缩写,除非缩写已是一种公认的约定,如URL、HTML
不要使用类型前缀。
不要使用下划线字符(_)。
接口
接口命名与类相同,唯一区别是给接口名称加上大写字母 I 前缀。
枚举 (Enum)
不要在Enum类型名称上使用Enum后缀,可根据使用场景添加后缀限定。
对大多数Enum类型使用单数名称,但是对作为位域的Enum类型使用复数名称。
总是将FlagsAttribute添加到位域Enum类型。
参数
使用描述性词语定义参数名称。
使用描述参数的含义的名称,而不要使用描述参数的类型的名称。
方法
使用动词或动词短语命名方法。
返回值是Bool值的方法以Is开头;
属性
使用名词或名词短语命名属性。
返回值是Bool值的属性以Is开头;
考虑用与属性的基础类型相同的名称创建属性。
事件
使用动词、动名词描述事件名称。
对委托定义使用Event后缀。
对事件定义使用 EventHandler 后缀。
用 EventArgs 后缀命名事件参数类。
不要在非动作事件声明上使用on前缀。
常量 (const)
所有单词大写,多个单词之间用下划线字符(_)隔开。
字段
禁止使用public修饰字段。
private、protected 使用 Camel 大小写。
属性的私有变量添加下划线字符(_)前缀
静态字段
使用名词、名词短语或者名词的缩写命名静态字段。
尽可能使用静态属性而不是公共静态字段。
集合
集合的命名建议用复数形式。
措词
避免使用与常用的.NET框架命名空间类名称冲突。
避免使用和C#关键字冲突的标识符。
语句规范
单行语句
每行最多包含一个语句。如
a++; //推荐
b--; //推荐
a++; b--; //不推荐
复合语句
复合语句是指类似“父语句{子语句;子语句;}”的语句,要求:
子语句要缩进。
左花括号{ 在复合语句父语句的下一行并与之对齐,单独成行。
即使只有一条子语句要不要省略花括号 {}。 如
while (d + = s++)
{
n++;
}
表达式
避免在表达式中用赋值语句
避免对浮点类型做等于或不等于判断
类型转换
尽量避免类型转换。
如果不得不进行类型转换,尽量用显式方式。
return 语句
return语句中不使用括号,除非它能使返回值更加清晰。如
return;
return myDisk.size();
return (size ? size : defaultSize);
if、 if-else、if else-if 语句
if (condition)
{
statements;
}
if (condition)
{
statements;
}
else
{
statements;
}
if (condition)
{
statements;
}
else if (condition)
{
statements;
}
else
{
statements;
}
for、foreach 语句
for (initialization; condition; update)
{
statements;
}
foreach (object obj in array)
{
statements;
}
注意:
在循环过程中不要修改循环计数器。
禁止出现空循环。
while 语句
while (condition)
{
statements;
}
do - while 语句
do
{
statements;
} while (condition);
switch - case 语句
switch (condition) { case 1: statements; break; case 2: statements; break; default: statements; break; }
注意:
语句switch中的每个case各占一行。
语句switch中的case按字母顺序排列。
为所有switch语句提供default分支。
所有的非空 case 语句必须用 break; 语句结束。
try - catch 语句
try { statements; } catch (ExceptionClass e) { statements; } finally { statements; }
using 块语句
using (object) { statements; }
goto 语句
禁止使用goto语句
开发建议
- 程序充分测试绝对是有必要的
- 发布时生成Release版本,Web站点禁用调试模式
- 类内函数、属性和变量的调用在前面加上this.
- 静态元素(元素包括变量和方法)的调用,一定要加类名避免阅读混乱。
- 引用类型转换:使用as运算符,优点是转换不成功时,返回值为null,不抛出异常。
- 避免在循环中创建对象,在需要逻辑分支中创建对象,使用常量避免创建对象
- 避免循环次数为1的循环。
- 使用变量保存中间数据,而不是每次都计算,避免不必要的损失性能。
- 在需要大量字符串连接的时候,使用StringBuilder类。
- 如果能计算出字符串长度的话,则按这个长度来设定StringBuilder类Buffer 的初值。
- 在需要使用格式化字符串时,使用String.Format而不是使用字符串相加。
- 尽量避免数据类型转换,避免装箱和拆箱,使用值类型的ToString方法
- 禁止使用ASP.NET中的服务器端控件,在MVC中已经没有这些内容了。
- Aspx使用asp:Repeater控件或者使用模板/字符串输出,让代码输出格式可控。
- 用asp:Literal替换asp:Label,asp:Literal输出是干净的。
- 少用PostBack机制,多用Ajax
- 浮点运算Float并不比Double要快,当转换为Int时,Double可能更高。
- 右移和预计算优化是有效的
- 减少冗余运算和无用的重复调用
- 善用Hashtable,当数据量极大时Hashtable的扩容消耗极其惊人,一般使用Dict就足够了。
- 在资源不再使用时手动释放,不要等待GC的回收,GC并不总是靠谱。
- 减少数据库的连接次数和打开时间,不再使用时尽快关闭
- 使用存储过程提高语句执行效率,节省网络传输
- 优化查询语句,详见SQL开发规范
- 优化服务器设置以符合系统需要
- 只要可能,就缓存数据和页输出
- 使用缓存考虑命中率,选择合适的缓存策略
- 选择适合页面或应用程序的数据查看机制
- 将DataReader用于快速只进数据游标,优点是省内存,缺点是占用连接时间长
- 禁止引入COM 组件
- 采用 Server.Transfer 语法进行重定向,该方法可避免客户端重定向,同时保持URL不变。
- 如有必要,调整应用程序每个辅助进程的线程数
- 适当地使用公共语言运行库的垃圾回收器和自动内存管理
- 如果有大型 Web 应用程序,可考虑执行预批编译
- 异常处理的最重要原则就是:不要吃掉异常。
- 除非要处理,否则就不要捕获异常
- 只在必要时保存服务器控件ViewState
- 减少对服务器的不必要的请求,Page.IsPostBack是个好用的工具
- 如果有可能,禁用Session
- 反射是一项很好用的技术,很方便,但不要滥用。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
2017-01-03 c# 字符串连接使用“+”和string.format格式化两种方式