.Net项目命名规范
dotShare系统改造项目的建设过程中,将涉及到Visual Studio.NET、Web站点,业务对象及数据库,同时项目人员包括设计人员、开发人员和测试人员等较多。为了保持应用程序、组件、文件的一致性,便于阅读和管理代码和结构,提高开发效率和产品的标准化,特制订一套开发规范和标准(包括命名规范和编码规范)。好的编码约定可使源代码严谨、可读性强且语意清楚,做到与其它语言约定相一致,并且提高直观性。希望设计/开发人员严格遵守此套开发规范和标准,并落实到自己的设计与代码程序中。
命名规范将包括:编程命名规范,业务对象命名规范,数据库命名规范,Web站点结构命名规范等。
编码规范将包括:C#编码规范,第三方模块使用规范等
本命名规范主要针对使用Visual Stdio.Net(VB.NET语言及C#语言)规范,即编程命名规范部分。请注意:在本项目过程中,C#将作为首选语言,如非特别必要,不要选用VB.NET。
2 变量命名的总原则
变量命名的总原则是一个通用性的原则,本规范后续章节中的命名规则都应当符合这些总原则。
2.1 一般性规则
· 变量名称应当准确完整地描述了变量的含义
· 名称应当反映了业务上的问题而不是技术上或编程上的解决方法
· 名称的长度应当足够长
· 名称的最后一部分应当有限定符
· 应当用Count, Index或Nbr代替Num, No.
2.2 对特定类型数据的命名
· 循环计数变量的的名称应当有含义(如果循环语句的长度超过了两行或者存在着嵌套循环,尽量避免使用I,j,k之类的变量,应该使用有意义的变量)
· 临时变量的命名应当有意义
· 所有布尔型变量的命名能够直接从名称上看出为真的条件
· 枚举类型的变量名称应当包含了基础类型,能够方便的分辨变量的类型。例如:用Color变量表示 ColorRed, ColorGreen枚据类型的值。
· 命名的常量应当代表了抽象的实体而非他们所代表的值
· 从变量命名中应当可以看出变量的作用域是局部变量,模块变量或者全局变量
· 变量的名称中不同的单词首字母要大写,以方便阅读
2.3 关于短名称的使用
· 如果不是绝对必须,尽量避免使用短的名称
· 如果变量中单词的缩写只能缩短一两个字符则使用单词的完全拼写
· 所有单词的缩写规则应当一致
2.4 其它应当避免的命名问题
· 名称具有误导性
· 两个不同的命名具有相似的含义
· 不同的命名拼写很相似,仅差一两个字符
· 在变量名称中不应当使用数字
· 完全和变量含义不相关的命名
3 Visual Stdio.Net
3.1 大写样式
使用下面的三种大写标识符约定。
将标识符的首字母和后面连接的每个单词的首字母都大写。可以对三字符或更多字符的标识符使用 Pascal 大小写。例如:
BackColor
标识符的首字母小写,而每个后面连接的单词的首字母都大写。例如:
backColor
大写
标识符中的所有字母都大写。仅对于由两个或者更少字母组成的标识符使用该约定。例如:
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 |
参数 |
Camel |
typeName |
属性 |
Pascal |
BackColor |
受保护的实例字段 |
Camel |
redValue 注意 很少使用。属性优于使用受保护的实例字段。 |
公共实例字段 |
Pascal |
RedValue 注意 很少使用。属性优于使用公共实例字段。 |
3.2 区分大小写
为了避免混淆和保证跨语言交互操作,请遵循有关区分大小写的使用的下列规则:
- 不要使用要求区分大小写的名称。对于区分大小写和不区分大小写的语言,组件都必须完全可以使用。不区分大小写的语言无法区分同一上下文中仅大小写不同的两个名称。因此,在创建的组件或类中必须避免这种情况。
- 不要创建仅是名称大小写有区别的两个命名空间。例如,不区分大小写的语言无法区分以下两个命名空间声明。
namespace ee.cummings;
namespace Ee.Cummings;
- 不要创建具有仅是大小写有区别的参数名称的函数。下面的示例是不正确的。
void MyFunction(string a, string A)
- 不要创建具有仅是大小写有区别的类型名称的命名空间。在下面的示例中,Point p 和 POINT p 是不适当的类型名称,原因是它们仅是大小写有区别。
System.Windows.Forms.Point p
System.Windows.Forms.POINT p
- 不要创建具有仅是大小写有区别的属性名称的类型。在下面的示例中,int Color 和 int COLOR 是不适当的属性名称,原因是它们仅是大小写有区别。
int Color {get, set}
int COLOR {get, set}
- 不要创建具有仅是大小写有区别的方法名称的类型。在下面的示例中,calculate 和 Calculate 是不适当的方法名称,原因是它们仅是大小写有区别。
void calculate()
void Calculate()
3.3 缩写
为了避免混淆和保证跨语言交互操作,请遵循有关区缩写的使用的下列规则:
- 不要将缩写或缩略形式用作标识符名称的组成部分。例如,使用
GetWindow
,而不要使用GetWin
。 - 不要使用计算机领域中未被普遍接受的缩写。
- 在适当的时候,使用众所周知的缩写替换冗长的词组名称。例如,用
UI
作为 User Interface 的缩写,用OLAP
作为 On-line Analytical Processing 的缩写。 - 在使用缩写时,对于超过两个字符长度的缩写请使用 Pascal 大小写或 Camel 大小写。例如,使用 HtmlButton 或 HTMLButton。但是,应当大写仅有两个字符的缩写,如,
System.IO
,而不是System.Io
。 - 不要在标识符或参数名称中使用缩写。如果必须使用缩写,对于由多于两个字符所组成的缩写请使用 Camel 大小写,虽然这和单词的标准缩写相冲突。
3.4 措词
避免使用与常用的 .NET 框架命名空间重复的类名称。例如,不要将以下任何名称用作类名称:System、Collections、Forms 或 UI。有关 .NET 框架命名空间的列表,请参阅类库。
另外,避免使用和以下关键字冲突的标识符。
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 |
|
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 |
|
|
3.5 避免类型名称混淆
不同的编程语言使用不同的术语标识基本托管类型。类库设计人员必须避免使用语言特定的术语。请遵循本节中描述的规则以避免类型名称混淆。
使用描述类型的含义的名称,而不是描述类型的名称。如果参数除了其类型之外没有任何语义含义,那么在这种罕见的情况下请使用一般性名称。例如,支持将各种数据类型写入到流中的类可以有以下方法。
[Visual Basic]
Sub Write(value As Double);
Sub Write(value As Single);
Sub Write(value As Long);
Sub Write(value As Integer);
Sub Write(value As Short);
[C#]
void Write(double value);
void Write(float value);
void Write(long value);
void Write(int value);
void Write(short value);
不要创建语言特定的方法名称,如下面的示例所示。
[Visual Basic]
Sub Write(doubleValue As Double);
Sub Write(singleValue As Single);
Sub Write(longValue As Long);
Sub Write(integerValue As Integer);
Sub Write(shortValue As Short);
[C#]
void Write(double doubleValue);
void Write(float floatValue);
void Write(long longValue);
void Write(int intValue);
void Write(short shortValue);
如果有必要为每个基本数据类型创建唯一命名的方法,那么在这种极为罕见的情况下请使用通用类型名称。下表列出基本数据类型名称和它们的通用替换。
C# 类型名称 |
Visual Basic 类型名称 |
JScript 类型名称 |
Visual C++ 类型名称 |
Ilasm.exe 表示形式 |
通用类型名称 |
sbyte |
Sbyte |
sByte |
char |
int8 |
SByte |
byte |
Byte |
byte |
unsigned char |
unsigned int8 |
Byte |
short |
Short |
short |
short |
int16 |
Int16 |
ushort |
UInt16 |
ushort |
unsigned short |
unsigned int16 |
UInt16 |
int |
Integer |
int |
int |
int32 |
Int32 |
uint |
UInt32 |
uint |
unsigned int |
unsigned int32 |
UInt32 |
long |
Long |
long |
__int64 |
int64 |
Int64 |
ulong |
UInt64 |
ulong |
unsigned __int64 |
unsigned int64 |
UInt64 |
float |
Single |
float |
float |
float32 |
Single |
double |
Double |
double |
double |
float64 |
Double |
bool |
Boolean |
boolean |
bool |
bool |
Boolean |
char |
Char |
char |
wchar_t |
char |
Char |
string |
String |
string |
String |
string |
String |
object |
Object |
object |
Object |
object |
Object |
例如,支持将从流读取各种数据类型的类可以有以下方法。
[Visual Basic]
ReadDouble()As Double
ReadSingle()As Single
ReadInt64()As Long
ReadInt32()As Integer
ReadInt16()As Short
[C#]
double ReadDouble();
float ReadSingle();
long ReadInt64();
int ReadInt32();
short ReadInt16();
前面的示例优于下面的语言特定的替换。
[Visual Basic]
ReadDouble()As Double
ReadSingle()As Single
ReadLong()As Long
ReadInteger()As Integer
ReadShort()As Short
[C#]
double ReadDouble();
float ReadFloat();
long ReadLong();
int ReadInt();
short ReadShort();
3.6 命名空间命名指南
命名命名空间时的一般性规则是使用公司名称,后跟技术名称和可选的功能与设计,如下所示。
CompanyName.TechnologyName[.Feature][.Design]
例如:
Microsoft.Media
Microsoft.Media.Design
给命名空间名称加上公司名称或者其他知名商标的前缀可以避免两个已经发布的命名空间名称相同的可能性。例如,Microsoft.Office
是由 Microsoft 提供的 Office Automation Classes 的一个适当的前缀。
在第二级分层名称上使用稳定的、公认的技术名称。将组织层次架构用作命名空间层次架构的基础。命名一个命名空间,该命名空间包含为具有 .Design
后缀的基命名空间提供设计时功能的类型。例如,System.Windows.Forms.Design 命名空间包含用于设计基于 System.Windows.Forms 的应用程序的设计器和相关的类。
嵌套的命名空间应当在包含它的命名空间中的类型上有依赖项。例如,System.Web.UI.Design 中的类依赖于 System.Web.UI 中的类。但是,System.Web.UI 中的类不依赖于 System.UI.Design 中的类。
应当对命名空间使用 Pascal 大小写,并用句点分隔逻辑组件,如 Microsoft.Office.PowerPoint
中所示。如果您的商标使用非传统的大小写,请遵循您的商标所定义的大小写,即使它与规定的 Pascal 大小写相背离。例如,命名空间 NeXT.WebObjects
和 ee.cummings
阐释了对于 Pascal 大小写规则的适当背离。
如果在语义上适当,使用复数命名空间名称。例如,使用 System.Collections
而不是 System.Collection
。此规则的例外是商标名称和缩写。例如,使用 System.IO
而不是 System.IOs
。
不要为命名空间和类使用相同的名称。例如,不要既提供 Debug
命名空间也提供 Debug
类。
最后,请注意命名空间名称不必非得与程序集名称相似。例如,如果命名程序集 MyCompany.MyTechnology.dll
,它没有必要非得包含 MyCompany.MyTechnology
命名空间。
在本项目中,最外层的命名空间采用DigitalCompany.DotShare。
3.7 类命名指南
以下规则概述命名类的指南:
- 使用名词或名词短语命名类。
- 使用 Pascal 大小写。
- 少用缩写。
- 不要使用类型前缀,如在类名称上对类使用
C
前缀。例如,使用类名称FileStream
,而不是CFileStream
。 - 不要使用下划线字符 (_)。
- 有时候需要提供以字母 I 开始的类名称,虽然该类不是接口。只要 I 是作为类名称组成部分的整个单词的第一个字母,这便是适当的。例如,类名称 IdentityStore 是适当的。
- 在适当的地方,使用复合单词命名派生的类。派生类名称的第二个部分应当是基类的名称。例如,
ApplicationException
对于从名为Exception
的类派生的类是适当的名称,原因是ApplicationException
是一种Exception
。请在应用该规则时进行合理的判断。例如,Button
对于从Control
派生的类是适当的名称。尽管按钮是一种控件,但是将Control
作为类名称的一部分将使名称不必要地加长。
下面是正确命名的类的示例。
[Visual Basic]
Public Class FileStream
Public Class Button
Public Class String
[C#]
public class FileStream
public class Button
public class String
3.8 接口命名指南
以下规则概述接口的命名指南:
- 用名词或名词短语,或者描述行为的形容词命名接口。例如,接口名称 IComponent 使用描述性名词。接口名称 ICustomAttributeProvider 使用名词短语。名称 IPersistable 使用形容词。
- 使用 Pascal 大小写。
- 少用缩写。
- 给接口名称加上字母
I
前缀,以指示该类型为接口。 - 在定义类/接口对(其中类是接口的标准实现)时使用相似的名称。两个名称的区别应该只是接口名称上有字母
I
前缀。 - 不要使用下划线字符 (_)。
以下是正确命名的接口的示例。
[Visual Basic]
Public Interface IServiceProvider
Public Interface IFormatable
[C#]
public interface IServiceProvider
public interface IFormatable
以下代码示例阐释如何定义 IComponent 接口及其标准实现 Component 类。
[Visual Basic]
Public Interface IComponent
' Implementation code goes here.
End Interface
Public Class Component
Implements IComponent
' Implementation code goes here.
End Class
[C#]
public interface IComponent
{
// Implementation code goes here.
}
public class Component: IComponent
{
// Implementation code goes here.
}
3.9 特性命名指南
应该总是将后缀 Attribute 添加到自定义属性类。以下是正确命名的属性类的示例。
[Visual Basic]
Public Class ObsoleteAttribute
[C#]
public class ObsoleteAttribute{}
3.10 枚举类型命名指南
枚举 (Enum) 值类型从 Enum 类继承。以下规则概述枚举的命名指南:
- 对于 Enum 类型和值名称使用 Pascal 大小写。
- 少用缩写。
- 不要在 Enum 类型名称上使用
Enum
后缀。 - 对大多数 Enum 类型使用单数名称,但是对作为位域的 Enum 类型使用复数名称。
- 总是将 FlagsAttribute 添加到位域 Enum 类型。
3.11 静态字段命名指南
以下规则概述静态字段的命名指南:
- 使用名词、名词短语或者名词的缩写命名静态字段。
- 使用 Pascal 大小写。
- 对静态字段名称使用匈牙利语表示法前缀。
- 建议尽可能使用静态属性而不是公共静态字段。
3.12 参数命名指南
以下规则概述参数的命名指南:
- 使用描述性参数名称。参数名称应当具有足够的描述性,以便参数的名称及其类型可用于在大多数情况下确定它的含义。
- 对参数名称使用 Camel 大小写。
- 使用描述参数的含义的名称,而不要使用描述参数的类型的名称。开发工具将提供有关参数的类型的有意义的信息。因此,通过描述意义,可以更好地使用参数的名称。少用基于类型的参数名称,仅在适合使用它们的地方使用它们。
- 不要使用保留的参数。保留的参数是专用参数,如果需要,可以在未来的版本中公开它们。相反,如果在类库的未来版本中需要更多的数据,请为方法添加新的重载。
- 不要给参数名称加匈牙利语类型表示法的前缀。
以下是正确命名的参数的示例。
[Visual Basic]
GetType(typeName As String)As Type
Format(format As String, object [] args)As String
[C#]
Type GetType(string typeName)
string Format(string format, args() As object)
3.13 方法命名指南
以下规则概述方法的命名指南:
- 使用动词或动词短语命名方法。
- 使用 Pascal 大小写。
以下是正确命名的方法的实例。
RemoveAll()
GetCharArray()
Invoke()
3.14 属性命名指南
以下规则概述属性的命名指南:
- 使用名词或名词短语命名属性。
- 使用 Pascal 大小写。
- 不要使用匈牙利语表示法。
- 考虑用与属性的基础类型相同的名称创建属性。例如,如果声明名为 Color 的属性,则属性的类型同样应该是 Color。请参阅本主题中后面的示例。
以下代码示例阐释正确的属性命名。
[Visual Basic]
Public Class SampleClass
Public Property BackColor As Color
' Code for Get and Set accessors goes here.
End Property
End Class
[C#]
public class SampleClass
{
public Color BackColor
{
// Code for Get and Set accessors goes here.
}
}
以下代码示例阐释提供其名称与类型相同的属性。
[Visual Basic]
Public Enum Color
' Insert code for Enum here.
End Enum
Public Class Control
Public Property Color As Color
Get
' Insert code here.
End Get
Set
' Insert code here.
End Set
End Property
End Class
[C#]
public enum Color
{
// Insert code for Enum here.
}
public class Control
{
public Color Color
{
get {// Insert code here.}
set {// Insert code here.}
}
}
以下代码示例不正确,原因是 Color 属性是 Integer 类型的。
[Visual Basic]
Public Enum Color
' Insert code for Enum here.
End Enum
Public Class Control
Public Property Color As Integer
Get
' Insert code here.
End Get
Set
' Insert code here.
End Set
End Property
End Class
[C#]
public enum Color {// Insert code for Enum here.}
public class Control
{
public int Color
{
get {// Insert code here.}
set {// Insert code here.}
}
}
在不正确的示例中,不可能引用 Color 枚举的成员。Color.Xxx
将被解释为访问一个成员,该成员首先获取 Color 属性(在 Visual Basic 中为 Integer 类型,在 C# 中为 int 类型)的值,然后再访问该值的某个成员(该成员必须是 System.Int32 的实例成员)。
3.15 事件命名指南
以下规则概述事件的命名指南:
- 对事件处理程序名称使用 EventHandler 后缀。
- 指定两个名为 sender 和 e 的参数。sender 参数表示引发事件的对象。sender 参数始终是 object 类型的,即使在可以使用更为特定的类型时也如此。与事件相关联的状态封装在名为 e 的事件类的实例中。对 e 参数类型使用适当而特定的事件类。
- 用 EventArgs 后缀命名事件参数类。
- 考虑用动词命名事件。
- 使用动名词(动词的“ing”形式)创建表示事件前的概念的事件名称,用过去式表示事件后。例如,可以取消的 Close 事件应当具有 Closing 事件和 Closed 事件。不要使用 BeforeXxx/AfterXxx 命名模式。
- 不要在类型的事件声明上使用前缀或者后缀。例如,使用 Close,而不要使用 OnClose。
- 通常情况下,对于可以在派生类中重写的事件,应在类型上提供一个受保护的方法(称为 OnXxx)。此方法只应具有事件参数 e,因为发送方总是类型的实例。
以下示例阐释具有适当名称和参数的事件处理程序。
[Visual Basic]
Public Delegate Sub MouseEventHandler(sender As Object, e As MouseEventArgs)
[C#]
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
以下示例阐释正确命名的事件参数类。
[Visual Basic]
Public Class MouseEventArgs
Inherits EventArgs
Dim x As Integer
Dim y As Integer
Public Sub New MouseEventArgs(x As Integer, y As Integer)
me.x = x
me.y = y
End Sub
Public Property X As Integer
Get
Return x
End Get
End Property
Public Property Y As Integer
Get
Return y
End Get
End Property
End Class
[C#]
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; } }
}