鼎鼎知识库
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

2020.10.25代码规范.md 13KB

本篇代码规范中的C#部分源自苏州盛派网络科技有限公司创始人Jeffrey Su的《C#编码规范》,本篇是在Markdown下的复述和实践,并且加入前端和手机端的代码规范。

1、概述

1.1 为什么需要代码规范

  • 便于团队协作和维护
  • 方便阅读
  • 美观

1.2 类型

  • Pascal: BackColor
  • Camel: backColor

建议后端使用Pascal规范,前端使用Camel规范。

2、代码外观

2.1 每行字符数

不超过110个字符。

2.2 换行

当每行即将超出110个字符时,优先在逗号后换行,其次在操作符前换行。

2.3 缩进

4个空格。

Viusal Studio可在文本编辑器中设置。

2.4 空行

以下情况空两行

--接口和类的定义之间
--枚举和类的定义之间
--类与类的定义之间

以下情况空一行

--方法与方法之间
--属性与属性之间
--方法中变量声明与语句之间
--方法的不同逻辑块之间
--方法的返回语句与其它语句之间
--属性与方法之间
--属性与字段之间
--方法与字段之间
--注释与其它语句间

2.5 空格

关键字和左括号之间用空格

while (true)

方法名和左括号之间不使用空格

SayHello(string name)

方法中的多个参数用逗号隔开,每个逗号后加一个空格

ShowMessage(string name, int age)

二元操作符需要用空格和其后面的操作数隔开

a += c + d;
a = (a + b) / (c * d);

一元操作符、++、--与操作数之间不需要空格

n++

语句中的表达式之间用空格隔开

foreach(Person p in People)

2.6 括号

左括号不要紧靠关键字,中间用一个空格隔开

if (a > 0)

方法名之后的左括号不需要空格

void SayHello(string name)

2.7 花括号

左括号{放在关键字或方法名的下一行并与之对齐

if (true)
{

}

public int Add(int x, int y)
{

}

左括号与右括号对齐。
左括号单独成行,不与任何语句并列一行。
右括号建议加一个注释,方便找到与之对应的左括号。

while (true)
{
    if (isValid == true)
    {

    }//ifvalid
    else
    {

    }//not valid
}//end forever

3、注释

  • 修改代码的同时,也需要修改注释
  • 注释内容:有关用途、假设、限制、为什么存在等
  • 注释不应该产生多义:阐明代码就足够,不如注释中不该出现幽默
  • 注释中的印刷框:不推荐
  • 无关注释:在发布之前去掉
  • 对代码段的注释过于复杂:建议重构代码段
  • 对错误的修复和解决方法:建议使用注释

3.1 文档型注释

在接口、类、方法、属性、字段中使用注释,方便阅读和生成代码文档。

///<summary>
///<para>
///this is description
///</para>
///</summary>

3.2 不再使用或者临时屏蔽的代码。

/*
    [修改标识]
    [修改原因]
*/

3.3 单行注释

//this is comment
private int number;

if(a=='')//always true
{

}//always true
    

3.4 C#中的注释标签

  • 将说明中的文本标记为代码. <c>contentt</c>
  • 或等标记内的 <para>content</para>
  • 描述方法参数 <param name='name'>description</param>
  • paramref <paramref name="name" />
  • see <see cref="memeber" />
  • seealso <seealso cref="member" />
  • example <example>description</example>
  • code <code>content</code>
  • summary <summary>description</summary>
  • exception <exception cref="member">description</exception>
  • include
  • list
  • permission
  • remarks
  • returns
  • value

4、申明

4.1 每行声明一个变量,并按字母顺序排列

int level;//remark
int size;//remark

4.2 变量声明时初始化

int a = 0;

4.3 变量放在代码块的开始处

void MyMethod()
{
    int a = 0;
    ...
}

5、命名规范

  • 避免多义: AnalyzeThis()不推荐
  • 属性名称不需要包含类名:Book.BookTitle,不推荐
  • 在变量名称末尾或开头加计算限定符:MyAvg
  • 在变量名中使用互补配对:min/max, begin/end, open/close
  • bool类型变量名加is: isEnabled
  • 状态变量,具有多个可能的状态:documentType
  • 在循环中带上语义 ``` int NUM_DAYS_IN_WEEK = 10; for (int i = 0; i <=NUM_DAYS_IN_WEEK; i++) {

}


> 5.1 大小写规则

- 类:AppDomain
- 枚举类型:ErrorLevel
- 枚举值:FatalError
- 事件:ValueChanged
- 异常类:WebException
- 只读静态字段:RedValue
- 接口:IDisposable
- 方法:ToString
- 命名空间:System.Drawing
- 属性:BackColor
- 公共实例字段:RedValue
- 受保护的实例字段:redValue
- 私有的实例字段:redValue
- 参数:typeName
- 方法内的变量:backColor

> 5.2 缩写

- 计算机领域未被普遍接受的缩写:不推荐用
- 计算机领域众所周知的缩写:推荐用。比如UI作为User Interface的缩写
- 仅有两个字符的缩写:两个字符都大写。比如System.IO
- 超出两个字符的缩写:使用Pascal或Camel。比如HtmlButton
- 参数名称中可以缩写吗:不推荐

> 5.3 命名空间

- 格式:CompanyName.TechnologyName或ProjectName.[.Feature][.Design]
- 命名空间和类不能使用同样的名字

> 5.4 类

- 使用Pascal:MyClass
- 使用名称或名词短语
- 避免缩写,除非缩写是大众周知的
- 不使用类型前缀,推荐使用`FileStream`,不推荐使用`CFileStream`
- 不推荐使用下划线
- 有时可以以I开头:IdentityStore
- 派生类的第二部分是基类名称:`ApplicationException`

> 5.5 接口

- 使用描述性名词:`IComponent`
- 使用名词短语:`ICustomAttributeProvider`
- 使用形容词:`IPersistable`
- 使用Pascal: 
- 少用缩写
- I前缀
- 不要使用下划线

> 5.6 特性

public class ObsoleteAttribute {}


> 5.7 枚举

- 使用Pascal
- 少用缩写
- 不要在Enum类型名称上使用Enum后缀
- 对大多数Enume类型使用单数名称


> 5.8 参数

- 具有描述性
- 使用Camel
- 不要使用保留参数

> 5.9 方法
- 使用动词或动词短语
- 使用Pascal

> 5.10 属性

- 使用名词或名词短语
- 使用Pascal

> 5.11 事件

- 事件处理程序名称使用EvengHandler后缀
- 使用`sender`和`e`两个参数,`sender`表示引发事件的对象,`sender`的参数类型始终是`object`类型,即使在可以使用特定类型时也如此。与事件相关的状态封装在名为`e`的参数中,对`e`参数类型使用适当而特定的事件类。
- 用`EventArgs`后缀命名事件参数类
- 使用动词命名事件
- 使用进行时:`Closing`
- 使用过去式:`Closed`
- 不要使用BeforeXxx/AfterXxx命名模式
- 不要在类型的事件申明上使用前缀或后缀。比如,使用`Close`,不使用`OnClose`
- 在派生类中可以重写的事件,应在类型上提供一个受保护的方法,比如`OnXxx`

定义事件处理程序:

public delegate void MouseEventHandler(object sender, MouseEventArgs e);

public class MouseEventArgs : EventArgs {

int x;
int y;

public MouseEventArgs(int x, int y)
{
    this.x = x;
    this.y = y;
}

public int X
{
    get{
        return x;
    }
}

public int Y
{
    get
    {
        return y;
    }
}

}

> 5.12 常量

所有单词大写,多个单词之间用`_`分隔。

public const string Page_Title = “Welcome”;


> 5.13 字段

- private, protected类型的字段使用Camel
- public类型的字段使用Pascal
- 不轻易使用缩写,除非是众所周知的缩写
- 字段名称前不加前缀。比如,`g_`或`s_`
- 公共静态只读字段

public struct Color {

public static readonly Color Red = new Color();

public Color(int rgb)
{
    public Color(byte r, byte g, byte, b)
    {

    }
}

}


> 5.14 静态字段

- 使用名词、名词短语或者名词缩写
- 使用Pascal


> 5.15 集合

建议使用复数。

> 5.16 措词

不要将以下名称作为类名称:

AddHandler AddressOf Alias And Ansi As Assembly Auto Base Boolean ByRef Byte ByVal Call Case Catch CBool CByte Cchar CDate CDec CDbl Char Cint Class CLng CObj Const Cshort CSng CStr CType Date Decimal Declare Default Delegate Dim Do Double Each Else ElseIf End Enum Erase Error Event Exit ExternalSource False Finalize Finally Float For Friend Function Get GetType Goto Handles If Implements Imports In Inherits Integer Interface Is Let Lib Like Long Loop Me Mod Module MustInherit MustOverride MyBase MyClass Namespace New Next Not Nothing NotInheritable NotOverridable Object On Option Optional Or Overloads Overridable Overrides ParamArray Preserve Private Property Protected Public RaiseEvent ReadOnly ReDim Region REM RemoveHandler Resume Return Select Set Shadows Shared Short Single Static Step Stop String Structure Sub SyncLock Then Throw To True Try TypeOf Unicode Until volatile When While With WithEvents WriteOnly Xor Eval extends instanceof package var


# 6、语句

> 6.1 每行一个语句

> 6.2 复合语句

- 子语句要缩进
- 左花括号在父语句的下一行并与之对齐,单独成行
- 即使只有一条子语句也不要省略花括号

while (d += s++) {

n++;

}

> 6.3 return语句

return语句不使用括号,除非能使返回值更加清晰。

> 6.4 if, if-else, if else-if

if (condition) {

}

if (condition) {

} else {

}

if (condition) {

} else if (condition) {

} else {

}


> 6.5 for, foreach语句

for (initialization; condition; update) {

}

foreach (object obj in array) {

}


> 6.6 while

while (condition) {

}

while (condition);


> 6.7 do-while

do {

} while (condition);


> 6.8 switch-case

switch (condition) {

case 1:
    statements;
    break;
case 2:
    statements;
    break;
default:
    statements;
    break;

}

> 6.9 try-catch

try {

} catch (ExceptionClass ex) {

} finally {

}


> 6.10 using

using (object) {

}


> 6.11 got

goto Label1:

    statements;
Label:
    statements;
# 7、其它

> 7.1 文件头标注

文件头顶格(没有空行或空格),放置协议或关键说明

region Apache License Version 2.0

/*----------------------------------------------------------------

Copyright 2017 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md

----------------------------------------------------------------*/

endregion Apache License Version 2.0

紧跟协议或关键说明,为文件说明及版本更新内容
如:

/*----------------------------------------------------------------

Copyright (C) 2017 Senparc

文件名:ModifyDomainApi.cs
文件功能描述:修改域名接口


创建标识:Senparc - 20170601


修改标识:Senparc - 20171201
修改描述:v1.7.3 修复ModifyDomainApi.ModifyDomain()方法判断问题

修改标识:Senparc - 20171231
修改描述:v1.7.4 更新API地址

----------------------------------------------------------------*/

创建

其中“文件名”“文件功能描述”及“创建标识”必须在文件创建时时填写。

“创建标识”上下各空 2 行。


修改

每次更新文件必须填写“修改标识”及对应的“修改描述”。“修改标识”下,需要填写“修改人”和“时间”,使用“ - ”分隔。

每次修改填写的一组“修改标识”和“修改描述”中间不空行,每组修改信息上下各空 1 行(第一次修改是,上方空 2 行,配合“创建标识”标准)。


> 7.2 异步方法标记

严格按照以下换行格式:

if !NET35 && !NET40

    #region 异步方法

    /// <summary>
    /// 【异步方法】修改服务器地址 接口
    /// </summary>
    public static async Task<ModifyDomainResultJson> ModifyDomainAsync()
    {
        //...
    }

    #endregion

endif

```

重点注意:
1、#if#region 异步方法 中间没有空行,结束标签也是如此。
2、方法名称备注的 summary 信息必须以 【异步方法】 开头。
3、 #region 的下一行、#endregion 的上一行,应该为空行。