一、大小写约定
大小写样式
下列术语描述了标识符的不同大小写形式。
Pascal 大小写
将标识符的首字母和后面连接的每个单词的首字母都大写。可以对三字符或更多字符的标识符使用 Pascal 大小写。例如:
BackColor
大小写混合
标识符的首字母小写,而每个后面连接的单词的首字母都大写。例如:
backColor
大写
标识符中的所有字母都大写。例如:
IO
标识符的大小写规则
如果标识符由多个单词组成,请不要在各单词之间使用分隔符,如下划线(“_”)或连字符(“-”)等。而应使用大小写来指示每个单词的开头。
下列准则是用于标识符的通用规则。
对于由多个单词组成的所有公共成员、类型及命名空间名称,要使用 Pascal 大小写。
注意,这条规则不适用于实例字段。
对参数名称使用大小写混合。
下表汇总了标识符的大小写规则,并提供了不同类型标识符的示例。
标识符 |
大小写方式 |
示例 |
类 |
Pascal |
AppDomain |
枚举类型 |
Pascal |
ErrorLevel |
枚举值 |
Pascal |
FatalError |
事件 |
Pascal |
ValueChanged |
异常类 |
Pascal |
WebException |
只读的静态字段 |
Pascal |
RedValue |
接口 |
Pascal |
IDisposable |
方法 |
Pascal |
ToString |
命名空间 |
Pascal |
System.Drawing |
参数 |
Camel |
typeName |
属性 |
Pascal |
BackColor |
首字母缩写词是由术语或短语中各单词的首字母构成的单词。例如,HTML 是 Hypertext Markup Language 的首字母缩写。只有在公众广为认知和理解的情况下,才应在标识符中使用首字母缩写词。首字母缩写词不同于缩写词,因为缩写词是一个单词的缩写。例如,ID 是 identifier 的缩写。通常情况下,库名不应使用缩写词。
注意 |
可在标识符中使用的两个缩写词是 ID 和 OK。在采用 Pascal 大小写格式的标识符中,这两个缩写词的大小写形式应分别为 Id 和 Ok。如果在采用大小写混合格式的标识符中将这两个缩写词用作首个单词,则它们的大小写形式应分别为 id 和 ok。 |
首字母缩写词的大小写取决于首字母缩写词的长度。所有首字母缩写词应至少包含两个字符。为了便于这些准则的实施,如果某一首字母缩写词恰好包含两个字符,则将其视为短型首字母缩写词。包含三个或三个以上字符的首字母缩写词为长型首字母缩写词。
下列准则为短型和长型首字母缩写词指定了正确的大小写规则。标识符大小写规则优先于首字母缩写词大小写规则。
两字符首字母缩写词的两个字符都要大写,但当首字母缩写词作为大小写混合格式的标识符的首个单词时例外。
例如,名为 DBRate 的属性是一个采用 Pascal 大小写格式的标识符,它使用短型首字母缩写词 (DB) 作为首个单词。又如,名为 ioChannel 的参数是一个采用大小写混合格式的标识符,它使用短型首字母缩写词 (IO) 作为首个单词。
包含三个或三个以上字符的首字母缩写词只有第一个字符大写,但当首字母缩写词作为大小写混合格式的标识符的首个单词时例外。
例如,名为 XmlWriter 的类是一个采用 Pascal 大小写格式的标识符,它使用长型首字母缩写词作为首个单词。又如,名为 htmlReader 的参数是一个采用大小写混合格式的标识符,它使用长型首字母缩写词作为首个单词。
如果任何首字母缩写词位于采用大小写混合格式的标识符开头,则无论该首字母缩写词的长度如何,都不大写其中的任何字符。
例如,名为 xmlStream 的参数是一个采用大小写混合格式的标识符,它使用长型首字母缩写词 (xml) 作为首个单词。又如,名为 dbServerName 的参数是一个采用大小写混合格式的标识符,它使用短型首字母缩写词 (db) 作为首个单词。
复合词和常用术语的大小写规则
不要将所谓的紧凑格式复合词中的每个单词都大写。这种复合词是指写作一个单词的复合词,如“endpoint”。
例如,hashtable 是一个紧凑格式的复合词,应将其视为一个单词并相应地确定大小写。如果采用 Pascal 大小写格式,则该复合词为 Hashtable;如果采用大小写混合格式,则该复合词为 hashtable。若要确定某个单词是否是紧凑格式的复合词,请查阅最新的词典。
下表列出了不是紧凑格式复合词的一些常用术语。术语先以 Pascal 大小写格式显示,后面的括号中的是其大小写混合格式。
· BitFlag (bitFlag)
· FileName (fileName)
· LogOff (logOff)
· LogOn (logOn)
· SignIn (signIn)
· SignOut (signOut)
· UserName (userName)
· WhiteSpace (whiteSpace)
区分大小写
大小写准则只是为了使标识符更易于阅读和辨认。不能将大小写规则用作避免库元素之间的命名冲突的手段。
不要假定所有编程语言都区分大小写。事实并非如此。不能仅凭大小写区分名称。
二、程序集和DLL的名称
大多数情况下,程序集包含全部或部分可重用库,且它包含在单个动态链接库 (DLL) 中。一个程序集可拆分到多个 DLL 中,但这非常少见,在此准则中也没有说明。
程序集和 DLL 是库的物理组织,而命名空间是逻辑组织,其构成应与程序集的组织无关。命名空间可以且经常跨越多个程序集。
一定要为程序集 DLL 选择指示大的功能块(如 System.Data)的名称。程序集和 DLL 的名称不必对应于命名空间名称,但是在命名程序集时遵循命名空间名称这种做法是合理的。
考虑按下面的模式命名 DLL:
<Company>.<Component>.dll
其中 <Component> 包含一个或多个以圆点分隔的子句。
三、命名空间的名称
为命名空间选择的名称应指示命名空间中的类型所提供的功能。例如,System.Net.Sockets 命名空间包含的类型允许开发人员使用套接字通过网络进行通信。
命名空间名称的一般格式如下:
<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]
例如,Microsoft.WindowsMobile.DirectX。
使用公司名称作为命名空间的前缀以防止不同公司开发的命名空间具有相同的名称和前缀。
在命名空间名称的第二级使用稳定的、与版本无关的产品名称。
不要根据组织层次结构确定命名空间层次结构中的名称,因为公司的部门名称经过一段时间后可能会改变。
命名空间名称是长期使用的、不会更改的标识符。组织的不断发展和变化不应使命名空间名称过时。
使用 Pascal 大小写格式,并用句点分隔命名空间各部分(如 Microsoft.Office.PowerPoint)。如果您的品牌采用了非传统的大小写,应遵循您的品牌所定义的大小写,即使它与常用的命名空间大小写相背离也如是。
适当的时候可考虑使用复数命名空间名称。例如,使用 System.Collections 而不使用 System.Collection。但是,品牌名称和首字母缩写词属于此规则的例外情况。例如,使用 System.IO,而不要使用 System.IOs。
命名空间和其中的类型不要使用相同的名称。例如,不要在将“Debug”用作命名空间名称的同时,又在该命名空间中提供一个名为“Debug”的类。有些编译器要求对这种类型进行完全限定。
命名空间和类型的名称冲突
如果选择的命名空间或类型的名称与现有名称冲突,则库的用户将不得不对受影响的项的引用进行限定。在大多数开发情况中,都不应出现这种问题。
本节提供的某些准则适用于下面的命名空间类别:
· 应用程序模型命名空间
· 基础结构命名空间
· 核心命名空间
· 技术命名空间组
应用程序模型中的命名空间提供特定于应用程序中的某个类的功能集。例如,System.Windows.Forms 命名空间中的类型提供编写 Windows 窗体客户端应用程序所需的功能。System.Web 命名空间中的类型支持编写基于 Web 的服务器应用程序。通常,在同一应用程序中不会使用不同应用程序模型中的命名空间,因此,这降低了名称冲突影响使用您的库的开发人员的可能性。
基础结构应用程序提供专门的支持,很少在程序代码中进行引用。例如,程序开发工具所使用的 *.Designer 命名空间中的类型。*.Permissions 命名空间是基础结构命名空间的另一个示例。与基础结构命名空间中的类型的名称冲突不可能影响使用您的库的开发人员。
核心命名空间是 System.* 命名空间(不包括应用程序命名空间和基础结构命名空间)。System 和 System.Text 都是核心命名空间的示例。应尽可能避免与核心命名空间中的类型发生名称冲突。
属于特定技术的命名空间将具有相同的第一和第二级标识符 (Company.technology.*)。应避免在技术命名空间中出现名称冲突。
命名空间一般准则
不要引入宽泛的类型名称,如 Element、Node、Log 和 Message。在通常情况下,这样极可能导致类型名称冲突。应对宽泛的类型名称进行限定(例如 FormElement、XmlNode EventLog、SoapMessage)。
应用程序命名空间准则
不要在单个应用程序模型内为命名空间中的多个类型指定相同的名称。
例如,如果要编写 Windows 窗体应用程序开发人员要使用的特殊控件库,则不应引入名为 Checkbox 的类型,因为该应用程序模型已存在同名类型 (CheckBox)。
核心命名空间准则
不要指定会与核心命名空间中的任何类型发生冲突的类型名称。
例如,不要使用 Directory 作为类型名称,因为这会与 Directory 类型冲突。
技术命名空间准则
不要分配会与单个技术命名空间内的其他类型发生冲突的类型名称。
不要引入会导致技术命名空间的类型与应用程序模型命名空间中的类型发生冲突的类型名称(除非该技术不用于该应用程序模型)。
四、类、结构和接口的名称
通常,类型名称应该是名词短语,其中名词是由类型表示的实体。例如,Button、Stack 和 File 都具有名称,用于标识由类型表示的实体。从开发人员的角度选择标识实体的名称;名称应反映使用场合。
下面的准则适用于如何选择类型名称。
按照 Pascal 大小写格式,使用名词或名词短语(或偶尔使用形容词短语)为类、接口和值类型命名。
不要为类名加前缀(如字母 C)。
接口不适用此规则,它应以字母 I 开头。
考虑在派生类的末尾使用基类名称。
例如,从 Stream 继承的 Framework 类型以 Stream 结尾,从 Exception 继承的类型以 Exception 结尾。
为接口名称加上字母 I 前缀,以指示该类型为接口。
在定义类/接口对(其中类是接口的标准实现)时,一定要确保类和接口的名称除接口名称以字母 I 为前缀外,二者应完全相同。
例如,Framework 提供 IAsyncResult 接口和 AsyncResult 类。
泛型类型参数的名称
泛型是 .NET Framework 2.0 版的主要新功能。下面的准则适用于为泛型类型参数选择正确的名称。
用描述性名称为泛型类型参数命名,除非单个字母的名称已完全可以自我说明而无需描述性名称。
IDictionary 是一个符合此准则的接口的示例。
对具有一个单字母类型参数的类型,考虑将字母 T 用作这些类型的类型参数名称。
将字母 T 作为描述性类型参数名称的前缀。
考虑在参数名称中指示置于类型参数上的约束。例如,约束于 ISession 的参数可称为 TSession。
常见类型的名称
下面的准则提供的命名约定有助于开发人员了解某些类的使用场合。准则中提及的从某个其他类型继承的类型,指的是所有的继承者,而不只是直接继承的类型。例如,“向从 Exception 继承的类型添加 Exception 后缀”这一准则意味着在继承层次结构中具有 Exception 的任何类型都应该使用以 Exception 结尾的名称。
每条这样的准则还用来保留指定的后缀;除非类型满足该准则表述的条件,否则不应使用该后缀。例如,如果类型不是从 Exception 直接或间接继承的,则类型名称不能以 Exception 结尾。
向自定义属性类添加 Attribute 后缀。
ObsoleteAttribute 和 AttributeUsageAttribute 是符合此准则的类型名称。
向在事件中使用的类型(如 C# 事件的返回类型)的名称添加 EventHandler 后缀。
AssemblyLoadEventHandler 是符合此准则的委托名称。
向不是事件处理程序的委托的名称添加 Callback 后缀。
不要向委托添加 Delegate 后缀。
向扩展 System.EventArgs 的类添加 EventArgs 后缀。
不要从 System.Enum 类派生;使用当前所用语言支持的关键字。例如,在 C# 中应使用 enum 关键字。
向从 System.Exception 继承的类型添加 Exception 后缀。
向实现 System.Collections.IDictionary 或 System.Collections.Generic.IDictionary<TKey, TValue> 的类型添加 Dictionary 后缀。注意,System.Collections.IDictionary 是特定类型的集合,但此准则的优先级高于以下更为一般的集合准则。
向实现 System.Collections.IEnumerable、System.Collections.ICollection、System.Collections.IList、System.Collections.Generic.IEnumerable<T>、System.Collections.Generic.ICollection<T> 或 System.Collections.Generic.IList<T> 的类型添加 Collection 后缀。
向从 System.IO.Stream 继承的类型添加 Stream 后缀。
向从 System.Security.CodeAccessPermission 继承的类型或实现 System.Security.IPermission 的类型添加 Permission 后缀。
枚举的名称
不要在枚举值名称中使用前缀。例如,不要对 ADO 枚举使用 ad 之类的前缀,也不要对多格式文本枚举使用 rtf 之类的前缀,依此类推。
这还意味着不应在枚举值名称中包含枚举类型名称。下面的代码示例演示了不正确的枚举值命名。
C# |
复制代码 |
public enum Teams { TeamsAlpha, TeamsBeta, TeamsDelta } |
不要将 Enum 用作枚举类型的后缀。
不要在标志枚举的名称中添加 Flags 作为后缀。
对枚举使用单数名称,除非枚举值是位域。
对使用位域值的枚举(也称为标志枚举)使用复数名称。
五、类型成员的名称
类型包含以下几种成员:
· 方法
· 属性
· 字段
· 事件
本节中的准则有助于类库设计者为成员选择与 .NET Framework 一致的名称。
方法的名称
使用动词或动词短语作为方法的名称。
通常,方法对数据进行操作,因此,使用动词描述方法的操作可使开发人员更易于了解方法所执行的操作。定义由方法执行的操作时,应从开发人员的角度仔细选择明确的名称。不要选择描述方法如何执行其操作的动词,也就是说,不要使用实现细节作为方法名称。
属性的名称
使用名词、名词短语或形容词作为属性的名称。
名词短语或形容词适合于属性,因为属性保存数据。
不要使用与 Get 方法同名的属性。
例如,不要将一个属性命名为 EmployeeRecord,又将一个方法命名为 GetEmployeeRecord。开发人员会不知道使用哪个成员来完成其编程任务。
使用肯定性短语作为布尔值属性的名称(如使用 CanSeek 而不使用 CantSeek)。此外,还可以为布尔值属性添加前缀(如 Is、Can 或 Has),但要注意使用得当。
考虑为属性提供与其类型相同的名称。
如果某个属性已强类型化为某个枚举,则该属性可与该枚举同名。例如,如果有一个名为 CacheLevel 的枚举,则返回其中一个枚举值的属性也可以命名为 CacheLevel。
事件的名称
使用动词或动词短语作为事件的名称。
在为事件命名时,使用现在时或过去时表示时间上的前后概念。例如,在窗口关闭之前引发的关闭事件可命名为“Closing”,在窗口关闭之后引发的关闭事件可命名为“Closed”。
不要使用“Before”或“After”作为前缀或后缀来指示之前和之后发生的事件。
使用后缀 EventHandler 命名事件处理程序(用作事件类型的委托)。
在事件处理程序签名中使用命名为“sender”和“e”的两个参数。
sender 参数的类型应为 Object,e 参数应是 EventArgs 的实例或继承自 EventArgs 的实例。
使用 EventArgs 后缀命名事件参数类。
字段的名称
字段的命名准则适用于静态公共字段和静态受保护字段。不要定义公共实例字段或受保护实例字段。有关更多信息,请参见字段设计。
在字段名称中使用 Pascal 大小写格式。
使用名词或名词短语作为字段的名称。
不要在字段名称中使用前缀。例如,不要使用 g_ 或 s_ 来区分静态字段和非静态字段。
六、参数名
选择适当的参数名称可极大改善库的可用性。适当的参数名称应指示该参数会影响的数据或功能。
对参数名称使用 Camel 大小写。
使用描述性参数名称。
在大多数情况下,参数名称及其类型应足以确定参数的用法。
考虑使用反映参数含义的名称而不是反映参数类型的名称。
七、资源名
本主题中准则适用于可本地化的资源,如错误信息和菜单文本。
在资源键中使用 Pascal 大小写格式。
提供描述性标识符,而不要提供短标识符。尽量保持标识符的简洁性,但不要牺牲可读性。
不要使用公共语言运行库 (CLR) 编程语言中特定于语言的关键字。
在命名资源中只能使用字母数字字符和下划线。
使用点分隔符(“.”)以清晰的层次结构表示标识符。
例如,Menus.FileMenu.Close.Text 和 Menus.FileMenu.Close.Color 等名称符合此准则。
对异常消息资源使用下面的命名约定。资源标识符应由异常类型名称加上异常的短标识符构成,二者之间以点分隔。
例如,ArgumentException.BadEnumValue 符合此准则。