# 编码规范

# 文件

# 文件名字和类名字应该一致

MyClass.cs public class MyClass {}
1

# 布局

# 1. 避免在一个文件中写多个命名空间或者类

这可以让你代码更具有可读性,让他更容易的被找到根据文件名称

# 2. 命名空间

// .NET namespaces first
using System;
using System.Collections;
// Then any other namespaces in alphabetical order
using Company.Business;
using Company.Standard;
using Telerik.Ajax;
using Telerik.WebControls;
1
2
3
4
5
6
7
8

# 3.每个类布局顺序

  1. 内部枚举、结构体、类
  2. 成员变量和属性
  3. 构造、初始化、销毁方法
  4. 公有方法
  5. 私有方法

# 缩进

# 1. 基础为4个空格

// A Hello World! program in C#.
using System;
namespace HelloWorld
{
 class Hello
 {
  static void Main()
  {
Console.WriteLine("Hello World!");
  }
 }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 2. 一行最多130个字符

当一行放不下了,用下面的规则:

  • 在逗号之后换行
  • 在操作符之后换行
  • 新一行对齐前一行同样的表达式级别

方法调用换行实例:

优质:

LongMethodCall(expr1, expr2,
expr3, expr4, expr5);
1
2

劣质:

LongMethodCall(expr1, expr2
 ,expr3, expr4, expr5);
1
2

表达式换行实例:

优质:

var result = a * b / (c - g + f) +
 4 * z;
1
2

劣质:

var result = a * b / (c - g + 
 f) + 4 * z;
1
2

# 3. 行末的花括号需要放在新的一行

while (x == y)
{
 FirstMethod();
 SecondMethod();
}

LastMethod();
1
2
3
4
5
6
7

# 4. 必须使用花括号即使不需要

即使只有一行的 if 判断句,也需要添加。

if (x == y)
{
 DoSomething();
}
1
2
3
4

# 空格

规则:

  • 关键字后有一个空格:if,while
  • for循环的分号后有一个空格
  • 逗号后面有一个空格
  • 操作符后有一个空格:+,-,--
  • 不需要加空格在 ( 之后与 ) 之前

实例:

a = (b + c) * d;
while (true) 
DoSomething(a, b, c, d)
for (i = 0; i < 10; i++) 
1
2
3
4

# 命名

# 1. 所有命名应该是英语

在国际合作开发中英语更有优势

# 2. 对语言元素使用适当的大小写

TIP

帕斯卡命名法(Pascal casing):一句文本中的每个单词的首字母为大写

驼峰命名法(Camel casing):一句文本中的每个单词的首字母为大写,除了文本的首字母

语言元素 命名法 样例
Class, Struct Pascal AppDomain
Interface Pascal IBusinessService
Enumeration Pascal ErrorLevel
Enumeration values UPPER_CASE FATAL_ERROR
Event Pascal Click
Public field Camel listItem
Private field Camel _listItem
Protected field Camel mListItem
Constant field UPPER_CASE MAXIMUM_ITEM_NUMBER
Constant local variable UPPER_CASE MAXIMUM_ITEM_NUMBER
Read-only static field Pascal ReadValue
Local variable Camel listOfValues
Method Pascal ToString
Namespace Pascal System.Drawing
Parameter Camel typeName
Type parameter Pascal TView
Property Pascal BackColor

# 3.避免使用缩略语

除非全名过长:

  • 避免缩略超过5个字符
  • 缩略语必须是广泛的被知道的
  • 使用2个字符的大写缩略,使用Pascal命名方式对于长的缩略

优质:

UIControl
HtmlSource
1
2

劣质:

UiControl
HTMLSource
1
2

# 4. 布尔类型参数前缀

  • Can
  • Is
  • Has

TIP

避免使用布尔参数作代表反面的性质,例如: 使用 IsInitialized ,而不是 IsNotInitialized

# 5. 在参数或属性中不要包含该类的名字

优质:

Customer.Name
1

劣质:

Customer.CustomerNam
1

# 注释

  • 在注释定界符(//)和注释文本之间插入一个空格。
  • 使用 //
  • 使用内联注释来解释假设,已知问题和算法见解
  • 不要使用内联注释来解释明显的代码。 编写良好的代码可以自我记录。
  • 使用 // TODO
  • 重构建议使用 // TODO :Refactor(username_optional)

# 语言规范

# 1. 不要忽略写访问权限

需要在声明时,写全访问权限

# 2. 使用C#内置的数据类型名字,而不是用.NET通用类型

优质:

short
int
long
string
1
2
3
4

劣质:

Int16
Int32
Int64
String
1
2
3
4

# 3. 不要使用var

容易不知道变量类型,不易阅读。

# 4.使用默认初始化器赋值,而不是单独写赋值

优质:

ProcessStartInfo startInfo = new ProcessStartInfo("myapp.exe")
{
    StandardOutput = Console.Output,
    UseShellExecute = true
};
1
2
3
4
5

劣质:

ProcessStartInfo startInfo = new ProcessStartInfo("myapp.exe");

startInfo.StandardOutput = Console.Output;
startInfo.UseShellExecute = true;
1
2
3
4

# 5. 代码用法

代码 形式
变量 每一个声明一个变量
属性 不要加前缀 GetSet
不想要额外变量,简单的声明
public int MyVariable { get; private set; }
方法 最多7个参数
basethis 只在构造方法或override中使用
三元表达式 避免复杂的条件
迭代 不要在foreach语句中修改枚举项
异常 不要将异常用于流控制
只抛出你能处理的
使用验证来避免异常
Execption派生而不是ApplicationException
事件 在触发是需要检测是否为空
使用lock()而不是Monitor.Enter()
不要锁对象的类型或者this
锁一个私有的对象
Dispose() & Close() 如果它提供了,就要使用
时常记得声明
避免放多个类在一个文件中
Finalizers 不要用
使用C#的析构函数
不要创建Finalize()方法

# 6. 变量与类型

  1. 尽量初始化值在定义变量时
  2. 尽量选择最简单的数据类型
  3. 避免使用数字在代码里,使用常数或是枚举代替
  4. 声明 readonlystatic readonly 的变量而不是复杂的 常数类型
  5. 只对简单的类型声明常数
  6. 避免直接转化,使用 as 操作符然后检测是否为空
    object dataObject = LoadData();
    DataSet dataSet = dataObject as DataSet;
    
    if(dataSet != null)
    {...}
    
    1
    2
    3
    4
    5
  7. 始终使用for循环显式初始化引用类型的数组
  8. 避免对值类型装箱与拆箱
    int count = 1;
    object refCount = count; // Implicitly boxed.
    int newCount = (int)refCount; // Explicitly unboxed. 
    
    1
    2
    3
  9. 尝试对字符串文字使用@前缀,而不是转义的字符串
  10. 使用StringBuilder连接大量字符串(在循环内)
  11. 不要使用""或者string.Empty来判断空字符串,而是用string.IsNullOrEmpty()方法
  12. 避免在循环中分配隐藏的字符串。 使用String.Compare()区分大小写
// Bad!
int id = -1;
string name = "lance hunt";

for(int i=0; i < customerList.Count; i++)
{
    if(customerList[i].Name.ToLower() == name)
    {
        id = customerList[i].ID;
    }

}

// Good!
int id = -1;
string name = "lance hunt";

for(int i=0; i < customerList.Count; i++)
{
    // The "ignoreCase = true" argument performs a 
    // case-insensitive compare without new allocation.
    if(String.Compare(customerList[i].Name, name, true) == 0)
    {
        id = customerList[i].ID;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 7. 流程控制

  1. 避免在条件表达式中调用方法
  2. 避免使用递归,使用循环代替
  3. 避免使用foreach遍历不可变的值类型集合。 例如:字符串数组
  4. foreach中不要修改枚举项
  5. 仅将三元条件运算符用于简单条件。避免复杂的或复合的三元运算。示例:int result = isValid ? 9:4;
  6. 避免在if判断时,使用布尔值再加判断:
    // Bad!
    if (isValid == true)
    {...}
     // Good!
    if (isValid)
    {...}
    
    1
    2
    3
    4
    5
    6
  7. 避免在条件语句中赋值。示例 :if((i=2)==2){...}
  8. 避免使用复合条件表达式,使用布尔变量将零件拆分为多个可管理的表达式
    // Bad!
    if (((value > _highScore) && (value != _highScore)) && (value < _maxScore))
    {...}
    
    // Good!
    isHighScore = (value >= _highScore);
    isTiedHigh = (value == _highScore);
    isValid = (value < _maxValue);
    
    if ((isHighScore && ! isTiedHigh) && isValid) {...}
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  9. 仅将switch/case语句用于具有并行条件逻辑的简单操作
  10. 对于简短的条件序列和复杂的条件,优先使用嵌套if/else而不是switch/case
  11. 使用多态或委托来替换switch/case语句

# 8. 对象模型与API设计

  1. 避免过早的使用泛型
  2. 当设计已经很清晰了,才创建抽象类
  3. 做最简单的实现,这样重构才有意义
  4. 尽量使对象的生命周期是对用户是不可见的
  5. 始终把表现层和逻辑层分离
  6. 优先使用接口而不是抽象类
  7. 当使用设计模式时,在类名中加入设计模式名字后缀,如:BrdgeAdpterFactory
  8. 经常重构

# 参考

https://google.github.io/styleguide/csharp-style.html

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines

上次更新: 5/25/2021, 6:28:08 PM