本文根据微软 框架设计准则 整理而成
1. 命名准则#
1.1. 大小写约定#
若要区分标识符中的单词,请将标识符中每个单词的首字母大写。不要使用下划线来区分单词,或在标识符中的任何位置使用下划线。
1.1.1. PascalCasing 约定#
(用于除了参数名称外的所有标识符)将每个单词(包括长度超过两个字母的首字母缩写词)的第一个字符大写,如下示例所示:
PropertyDescriptor
HtmlTag两个字母的首字母缩写词是一种特殊情况,其中两个字母都大写,如: IOStream
1.1.2. camelCasing 约定#
(仅用于参数名称),将每个单词的第一个字符(除第一个单词之外)大写,如:
propertyDescriptor
htmlTag
ioStream✔️ 对于包含多个单词的所有公共成员、类型和命名空间名称,请使用 PascalCasing。
✔️ 使用 camelCasing 作为参数名称。
不同标识符类型的首字母大写规则表
| 标识符 | 大小写 | 示例 |
|---|---|---|
| 命名空间 | Pascal | namespace System.Security { ... } |
| 类型 | Pascal | public class StreamReader { ... } |
| 接口 | Pascal | public interface IEnumerable { ... } |
| 方法 | Pascal | public virtual string ToString(); |
| 属性 | Pascal | public int Length { get; } |
| 事件 | Pascal | public event EventHandler Exited; |
| 字段 | Pascal | public static readonly TimeSpan InfiniteTimeout;public const Min = 0; |
| 枚举值 | Pascal | public enum FileMode { Append, ... } |
| 参数 | Camel | public static int ToInt32(string value); |
1.1.3. 将组合词和常见术语的首字母大写#
为了实现首字母大写,大多数组合术语都被视为单个单词。
❌ 不要将所谓的“闭合形式”组合词中的每个首字母大写。
组合词字典
| Pascal | Camel | Not |
|---|---|---|
| BitFlag | bitFlag | |
| Callback | callback | |
| Canceled | canceled | |
| DoNot | doNot | |
| Endpoint | endpoint | |
| FileName | fileName | |
| Gridline | gridline | |
| Hashtable | hashtable | |
| Id | id | |
| Indexes | indexes | |
| LogOff | logOff | |
| LogOn | logOn | |
| Metadata | metadata | |
| Multipanel | multipanel | |
| Multiview | multiview | |
| Namespace | namespace | |
| Ok | ok | |
| Pi | pi | |
| Placeholder | placeholder | |
| SignIn | signIn | |
| SignOut | signOut | |
| UserName | userName | |
| WhiteSpace | whiteSpace | |
| Writable | writable |
1.1.4. 区分大小写#
外部可访问的任何 API 都不能单独依赖于大小写来区分同一上下文中的两个名称。
❌ 不要假设所有编程语言都区分大小写。它们不是。名称不能按大小写单独区分。
1.2. 通用命名约定#
1.2.1. 选词#
✔️ 选择易读的标识符名称。 如:使用 HorizontalAlignment 而不是 AlignmentHorizontal。
✔️ 可读性比简洁性更重要。 如:使用 CanScrollHorizontally 而不是 ScrollableX。
❌ 不要使用下划线、连字符或任何其他非字母数字字符。
❌ 不要使用匈牙利表示法。
❌ 避免使用与广泛应用的编程语言关键字冲突的标识符。 如:在 C# 中,尽量不要使用 @+关键字 定义标识符。
1.2.2. 使用缩写和首字母缩写词#
❌ 不要使用缩写或缩写词作为标识符名称的一部分。 如:使用 GetWindow 而不是 GetWin。
❌ 不要使用未被广泛接受的任何首字母缩写词,仅在必要时才使用。
1.2.3. 避免使用特定于语言的名称#
✔️ 使用有语义的名称,而不是类型名称的特定于语言的关键字。 如:使用 GetLength 而不是 GetInt
✔️ 在极少数情况下,如果标识符没有超出其类型的语义含义,则使用泛型 CLR 类型名称,而不是特定于语言的名称。 如:使用 ToInt64 而不是 ToLong
CLR 类型名称以及 C#、Visual Basic 和 C++ 的相应类型名称
| C# | Visual Basic | C++ | CLR |
|---|---|---|---|
| sbyte | SByte | char | SByte |
| byte | Byte | unsigne char | Byte |
| short | Short | short | Int16 |
| ushort | UInt16 | unsigne short | UInt16 |
| int | Integer | int | Int32 |
| uint | UInt32 | unsigne int | UInt32 |
| long | Long | __int64 | Int64 |
| ulong | UInt64 | unsigne __int64 | UInt64 |
| float | Single | float | Single |
| double | Double | double | Double |
| bool | Boolean | bool | Boolean |
| char | Char | wchar_t | Char |
| string | String | String | String |
| object | Object | Object | Object |
1.2.4. 命名现有 API 的新版本#
✔️ 创建现有 API 的新版本时,使用类似于旧 API 的名称。
✔️ 更喜欢添加后缀(而非前缀)来指示现有 API 的新版本。
✔️ 考虑使用全新但有意义的标识符,而不是添加后缀或前缀。
✔️ 使用数字后缀来指示现有 API 的新版本,尤其是当 API 的现有名称是唯一有意义的名称(例如,如果其是行业标准), 并且添加任何有意义的后缀(或更改名称)并非不是合适的选择时。
❌ 不要使用标识符的“前”(或类似的)后缀,将其与同一 API 的先前版本区分开。
✔️ 在引入在 64 位整数上操作的 API 版本(长整数)而不是在 32 位整数上操作时,可以使用后缀 “64”。 仅当存在现有的 32 位 API 时,才需要采用此方法;请勿对只有 64 位版本的新 API 使用此方法。
1.3. 程序集和 DLL 的名称#
✔️为程序集 DLL 选择名称,这些名称建议了大块功能,如 System.object。
程序集和 DLL 的名称不必与命名空间名称对应,但在命名程序集时遵循命名空间名称是合理的。 合理的经验法则是基于程序集中包含的命名空间的公共前缀来命名 DLL。
✔️考虑根据以下模式命名 DLL: <Company>.<Component>.dll
1.4. 命名空间的名称#
与其他命名准则一样,命名命名空间的目标是为程序员创建足够的清晰度,使其能够立即了解命名空间的内容。 以下模板指定命名空间的一般规则:
<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]✔️使用公司名称作为命名空间名称的前缀,以防不同公司的命名空间具有相同的名称。
✔️在命名空间名称的第二级使用稳定的独立于版本的产品名称。
❌ 不要使用组织层次结构作为命名空间层次结构中的名称的基础,因为公司内的组名通常是短期的。 围绕一组相关技术组织命名空间的层次结构。
✔️使用 PascalCasing,并使用句点分隔命名空间组件 (例如, Microsoft.Office.PowerPoint) 。 如果品牌采用 nontraditional 大小写,则应遵循品牌定义的大小写,即使它与常规命名空间大小写不符。
✔️考虑在适当的情况下使用复数命名空间名称。
❌ 命名空间和该命名空间中的类型不要使用相同的名称。
1.4.1. 命名空间和类型名称冲突#
❌ 不要引入泛型类型名称 Element ,例如 Node、Log 和 Message。 应限定翻新类型名称,如:FormElement、XmlNode、EventLog、SoapMessage
为避免不同类别的命名空间的类型名称冲突,有一些特定的准则。
- 应用程序模型命名空间
❌ 不要为单个应用程序模型中的命名空间中的类型指定相同的名称。
- 基础结构命名空间
- 核心命名空间
❌ 不要提供会与核心命名空间中的任何类型冲突的类型名称。
- 技术命名空间组
❌ 不要分配会与单个技术中的其他类型冲突的类型名称。
❌ 请勿引入技术命名空间和应用程序模型命名空间中的类型之间的类型名称冲突 (除非该技术不打算用于应用程序模型) 。
1.5. 类、结构和接口的名称#
✔️ 使用 PascalCasing 将类和结构命名为名词或名词短语。
✔️ 利用形容词短语或偶尔用名词或名词短语来命名接口。
❌ 不要为类名称指定前缀 (例如,C ) 。
✔️ 考虑用基类的名称结束派生类的名称。
✔️ 使用字母 I 来为接口名称加上前缀,以指示该类型是接口。
✔️ 确保在定义类接口对(其中类是接口的标准实现)时,接口名称上的 I 前缀仅有不同的名称。
1.5.1. 泛型类型参数的名称#
✔️ 使用描述性名称命名泛型类型参数,除非单个字母名称完全一目了然,并且描述性名称不会添加值。
✔️ 考虑使用 T 作为具有一个单字母类型参数的类型的类型参数名称。
✔️ 在描述性类型参数名称加上前缀 T 。
✔️ 考虑,指示对参数名称中的类型参数施加的约束。
1.5.2. 常见类型的名称#
当命名类型派生自或实现某些 .NET Framework 类型时,✔️按照下表中所述的指导原则进行操作。
| 基类型 | 派生/实现类型准则 |
|---|---|
System.Attribute |
✔️将后缀 “Attribute” 添加到自定义特性类的名称中。 |
System.Delegate |
✔️将后缀 “EventHandler” 添加到在事件中使用的委托的名称。 ✔️将后缀 “Callback” 添加到作为事件处理程序使用的委托的名称。 ❌ 不要将后缀 “Delegate” 添加到委托。 |
System.EventArgs |
✔️添加后缀 “EventArgs”。 |
System.Enum |
❌ 不要从此类派生;改为使用您的语言支持的关键字;例如,在 C# 中,使用 enum 关键字。 ❌ 不要添加后缀 “Enum” 或 “Flag”。 |
System.Exception |
✔️添加后缀 “Exception”。 |
IDictionary IDictionary<TKey,TValue> |
✔️添加后缀 “Dictionary”。 请注意, IDictionary 是一种特定类型的集合,但是此准则优先于下面的更常见的集合原则。 |
IEnumerable ICollection IList IEnumerable<T> ICollection<T> IList<T> |
✔️添加后缀 “Collection”。 |
System.IO.Stream |
✔️添加后缀 “Stream”。 |
CodeAccessPermission IPermission |
✔️添加后缀 “Permission”。 |
1.5.3. 命名枚举#
✔️ 为枚举使用单数类型名称,除非其值为位域。
✔️ 对将位域作为值的枚举使用复数类型名称,也称为标志枚举。
❌ 不要在枚举类型名称中使用 “Enum” 后缀。
❌ 不要在枚举类型名称中使用 “Flag” 或 “Flags” 后缀。
❌ 不要在枚举值名称上使用前缀 (例如,将 “ad” 用于 ADO 枚举,使用 “rtf” 进行丰富文本枚举等 ) 。
1.6. 类型成员的名称#
1.6.1. 方法的名称#
✔️ 为谓词或谓词短语指定方法名称。
1.6.2. 属性的名称#
✔️ 使用名词、名词短语或形容词名称属性。
❌ 没有与 “Get” 方法的名称相匹配的属性,如以下示例中所示:
public string TextWriter { get {...} set {...} } public string GetTextWriter(int value) { ... }
此模式通常意味着该属性事实上是一种方法。
✔️ 使用一个复数短语来描述集合中的项,而不是使用后跟 “List” 或 “Collection” 的短语来命名集合属性。
✔️ 使用赞成短语 (CanSeek 而不是 CantSeek) 来命名布尔属性 CantSeek 。 或者,还可以在布尔属性前面添加 “Is”、“Can” 或 “has” 前缀,但前提是在它添加值的位置。
✔️ 考虑为属性提供与其类型相同的名称。
1.7. 命名参数#
✔️ 在参数名称中使用 camelCasing。
✔️ 使用描述性参数名称。
✔️ 考虑使用基于参数含义而不是参数类型的名称。
1.7.1. 命名运算符重载参数#
✔️ 如果参数没有任何意义,确实要使用 left 和 right 进行二元运算符重载参数名称。
✔️ 对于参数,确实使用 value 一元运算符重载参数名称。
✔️ 考虑运算符重载参数有意义的名称,如果这样做会增加重要值。
❌ 不要对运算符重载参数名称使用缩写或数值索引。
1.8. 命名资源#
✔️ 在资源键中使用 PascalCasing。
✔️ 提供描述性而不是短标识符。
❌ 不要使用主要 CLR 语言的特定于语言的关键字。
✔️ 在命名资源中仅使用字母数字字符和下划线。
✔️ 对异常消息资源使用以下命名约定。 资源标识符应为异常类型名称和异常的简短标识符:
ArgumentExceptionIllegalCharacters
ArgumentExceptionInvalidName
ArgumentExceptionFileNameIsMalformed