“Microsoft 基本设计准则规则”代码分析规则集

可以使用“Microsoft 基本设计准则规则”规则集侧重于使您的代码更易于理解和使用。 如果项目包括库代码或者如果要实施最佳做法以更易于维护代码,则应加入此规则集。

“基本设计准则规则”包括“Microsoft 最少量建议规则”规则集中的所有规则。 有关最少量规则的列表,请参见 “Microsoft 最少量建议规则”代码分析规则集

下表介绍了“Microsoft 基本设计准则规则”规则集中的所有规则。

规则

说明

CA1000:不要在泛型类型中声明静态成员

调用泛型类型的静态成员时,必须指定该类型的类型参数。 当调用不支持推理的泛型实例成员时,必须指定该成员的类型参数。 在上述两种情况下,用于指定类型参数的语法不同,但很容易混淆。

CA1002:不要公开泛型列表

System.Collections.Generic.List<(Of <(T>)>) 是针对性能(而非继承)设计的泛型集合。 因此,List 不包含任何虚拟成员。 应改为公开针对继承设计的泛型集合。

CA1003:使用泛型事件处理程序实例

类型所含的某个委托返回 void,该委托的签名包含两个参数(第一个参数是对象,第二个参数是可以分配给 EventArgs 的类型),而且包含程序集针对的是 .NET Framework 2.0。

CA1004:泛型方法应提供类型参数

推理是指由传递给泛型方法的参数的类型来确定该方法的类型参数,而不是显式指定类型参数。 若要启用推理,泛型方法的参数签名必须包含与该方法的类型参数属于相同类型的参数。 在这种情况下,不必指定类型参数。 如果对所有类型参数都使用推理,则调用泛型实例方法和非泛型实例方法的语法完全相同;这简化了泛型方法的可用性。

CA1005:避免泛型类型的参数过多

泛型类型包含的类型参数越多,越难以知道并记住每个类型参数各代表什么。 它通常有一个类型参数,如 List<T> 中,而在某些情况下有两个类型参数,如 Dictionary<TKey, TValue> 中。 但是,如果有两个以上的类型参数,则大多数用户都会感到过于困难。

CA1006:不要将泛型类型嵌套在成员签名中

嵌套类型参数是一个类型参数,也是一个泛型类型。 若要调用签名包含嵌套类型参数的成员,用户必须实例化一个泛型类型,并将此类型传递到另一个泛型类型的构造函数。 所需的过程和语法很复杂,应当避免。

CA1007:在适用处使用泛型

外部可见方法包含类型为 System.Object 的引用参数。 使用泛型方法使受约束的所有类型都可以传递给该方法,而比不先将类型强制转换为引用参数类型。

CA1008:枚举应具有零值

像其他值类型一样,未初始化枚举的默认值为零。 无标志特性的枚举应定义零值的成员,这样默认值即为该枚举的有效值。 如果应用了 FlagsAttribute 特性的枚举定义值为零成员,则该成员的名称应为“None”,以指示枚举中尚未设置值。

CA1010:集合应实现泛型接口

若要扩大集合的用途,应实现某个泛型集合接口。 然后,可以使用该集合来填充泛型集合类型。

CA1011:考虑将基类型作为参数传递

在方法声明中将基类型指定为参数时,可以将派生自基类型的任何类型作为相应的变量传递给方法。 如果不需要派生参数类型提供的其他功能,则使用基类型将使方法可以得到更广泛的使用。

CA1012:抽象类型不应具有构造函数

抽象类型的构造函数只能由派生类型调用。 由于公共构造函数用于创建类型的实例,但无法为抽象类型创建实例,因此具有公共构造函数的抽象类在设计上是错误的。

CA1013:重载加法方法和减法方法时重载相等运算符

公共或受保护类型实现加或减运算符时没有实现相等运算符。

CA1014:用 CLSCompliantAttribute 标记程序集

公共语言规范 (CLS) 定义了程序集在跨编程语言使用时必须符合的命名限制、数据类型和规则。 好的设计要求所有程序集用 CLSCompliantAttribute 显式指示 CLS 合规性。 如果程序集没有此特性,则该程序集即不合规。

CA1017:用 ComVisibleAttribute 标记程序集

ComVisibleAttribute 决定 COM 客户端如何访问托管代码。 合理的设计指出程序集将显式指示 COM 可见性。 可以设置整个程序集的 COM 可见性,然后重写各个类型和类型成员的 COM 可见性。 如果此特性不存在,则程序集的内容对 COM 客户端可见。

CA1018:用 AttributeUsageAttribute 标记特性

当定义自定义特性时,用 AttributeUsageAttribute 标记该特性,以指示源代码中可以应用自定义特性的位置。 特性的含义和预定用法将决定它在代码中的有效位置。

CA1019:定义特性参数的访问器

特性可以定义强制实参,在对目标应用该特性时必须指定这些实参。 这些实参也称为位置实参,因为它们将作为位置形参提供给特性构造函数。 对于每一个强制变量,特性还必须提供一个相应的只读属性,以便可以在执行时检索该变量的值。 特性还可以定义可选实参,可选实参也称为命名实参。 这些变量按名称提供给特性构造函数,并且必须具有相应的读/写属性。

CA1023:索引器不应是多维的

索引器(即索引属性)应该使用一个索引。 多维索引器会大大降低库的可用性。

CA1024:在适用处使用属性

公共或受保护方法的名称以“Get”开头,没有采用任何参数或返回的值不是数组。 该方法可能很适于成为属性。

CA1025:用形参数组替换重复的实参

如果参数的具体数量未知且变量参数为相同类型或可作为相同类型传递,请使用参数数组代替重复参数。

CA1026:不应使用默认参数

在公共语言规范 (CLS) 中允许方法使用默认参数;但是 CLS 允许编译器忽略为这些参数分配的值。 为了跨编程语言维护所需的行为,必须使用提供默认参数的方法重载来替换使用默认参数的方法。

CA1027:用 FlagsAttribute 标记枚举

枚举是一种值类型,它定义一组相关的已命名常数。 如果可以按照有意义的方式组合一个枚举的已命名常数,则对该枚举应用 FlagsAttribute。

CA1028:枚举存储应为 Int32

枚举是一种值类型,它定义一组相关的已命名常数。 默认情况下,System.Int32 数据类型用于存储常量值。 尽管您可以更改此基础类型,然而对于大多数情况,既不需要,也不建议您这样做。

CA1030:在适用处使用事件

该规则检测名称通常用于事件的方法。 如果为响应明确定义的状态更改而调用一个方法,则应由事件处理程序调用该方法。 调用该方法的对象应引发事件而不是直接调用该方法。

CA1031:不要捕捉一般异常类型

不应捕捉一般异常。 捕捉更具体的异常,或者在执行 catch 块中的最后一条语句时重新引发一般异常。

CA1032:实现标准异常构造函数

如果不能提供完整的构造函数集,要正确处理异常将变得比较困难。

CA1034:嵌套类型不应是可见的

嵌套类型是在另一个类型的范围中声明的类型。 嵌套类型用于封装包含类型的私有实现详细信息。 如果用于此用途,则嵌套类型不应是外部可见的。

CA1035:ICollection 实现含有强类型成员

此规则要求 ICollection 实现提供强类型成员,以使用户在使用该接口提供的功能时不必将参数强制转换成 Object 类型。 此规则假定实现 ICollection 的类型这样做是为了管理其类型强于对象的实例的集合。

CA1036:重写可比较类型中的方法

公共或受保护类型实现 System.IComparable 接口。 它不重写 Object.Equals,也不重载表示相等、不等、小于或大于的语言特定运算符。

CA1038:枚举数应强类型化

此规则要求 IEnumerator 实现还提供 Current 属性的强类型版本,以使用户在使用该接口提供的功能时不必将返回值强制转换为强类型。

CA1039:列表已强类型化

此规则要求 IList 实现提供强类型成员,以使用户在使用该接口提供的功能时不必将参数强制转换成 System.Object 类型。

CA1041:提供 ObsoleteAttribute 消息

将类型或成员标以未指定其 ObsoleteAttribute.Message 属性的 System.ObsoleteAttribute 特性。 编译标有 ObsoleteAttribute 的类型或成员时,将显示特性的 Message 属性,为用户提供有关已过时类型或成员的信息。

CA1043:将整型或字符串参数用于索引器

索引器(即索引属性)应将整型或字符串类型用于索引。 这些类型一般用于为数据结构编制索引,并且提高库的可用性。 应仅限于在设计时无法指定特定整型或字符串类型的情况下使用 Object 类型。

CA1044:属性不应是只写的

虽然可以接受且经常需要使用只读属性,但设计准则禁止使用只写属性,因为允许用户设置值但又禁止该用户查看这个值不能提供任何安全性。 而且,如果没有读访问,将无法查看共享对象的状态,使其用处受到限制。

CA1046:不要对引用类型重载相等运算符

对于引用类型,相等运算符的默认实现几乎始终是正确的。 默认情况下,仅当两个引用指向同一对象时,它们才相等。

CA1047:不要在密封类型中声明受保护的成员

类型声明受保护的成员,使继承类型可以访问或重写该成员。 按照定义,不能继承密封类型,这表示不能调用密封类型上的受保护方法。

CA1048:不要在密封类型中声明虚拟成员

类型将方法声明为虚方法,使继承类型可以重写虚方法的实现。 按照定义,不能继承密封类型。 这使得虚方法对于密封类型没有意义。

CA1050:在命名空间中声明类型

应在命名空间内声明类型以避免名称冲突,并作为一种在对象层次结构中组织相关类型的方式。

CA1051:不要声明可见实例字段

字段的主要用途应是作为实现的详细信息。 字段应为 private 或 internal,并应通过使用属性公开这些字段。

CA1052:应密封静态容器类型

公共或受保护类型仅包含静态成员,而且没有用 sealed(C# 参考)(NotInheritable) 修饰符声明该类型。 应将不希望被继承的类型标以 sealed 修饰符,以免将其用作基类型。

CA1053:静态容器类型不应具有构造函数

公共或嵌套公共类型只声明了静态成员,但具有公共或受保护的默认构造函数。 由于调用静态成员不需要类型的示例,因此没必要使用构造函数。 为安全起见,字符串重载应使用字符串参数调用 URI 重载。

CA1054:URI 参数不应为字符串

如果某方法采用 URI 的字符串表示形式,则应提供采用 URI 类的实例的相应重载,该重载以安全的方式提供这些服务。

CA1055:URI 返回值不应是字符串

此规则假定该方法返回统一资源标识符 (URI)。 URI 的字符串表示形式容易导致分析和编码错误,并且可造成安全漏洞。 System.Uri 类以一种安全的方式提供这些服务。

CA1056:URI 属性不应是字符串

此规则假定属性表示统一资源标识符 (URI)。 URI 的字符串表示形式容易导致分析和编码错误,并且可造成安全漏洞。 System.Uri 类以一种安全的方式提供这些服务。

CA1057:字符串 URI 重载调用 System.Uri 重载

某个类型声明的方法重载与 System.Uri 参数仅在字符串参数的放置方面有所不同。 采用字符串参数的重载不调用采用 URI 参数的重载。

CA1058:类型不应扩展某些基类型

外部可见的类型扩展某些基类型。 请使用某个备选项。

CA1059:成员不应公开某些具体类型

具体类型是指具有一个完整实现因此可以实例化的类型。 若要使成员可以得到广泛使用,请将具体类型替换为建议的接口。

CA1064:异常应该是公共的

内部异常仅在其自己的内部范围内可见。 当异常超出内部范围后,只能使用基异常来捕获该异常。 如果内部异常是从 T:System.Exception、T:System.SystemException 或 T:System.ApplicationException 继承而来,外部代码将没有足够的信息了解如何处理该异常。

CA1500:变量名不应与字段名相同

实例方法声明一个名称与声明类型的实例字段匹配的参数或局部变量,从而导致错误。

CA1502:避免过度复杂

此规则通过方法来测量线性独立的路径的数量,该数量是由条件分支的数量和复杂度决定的。

CA1708:标识符不应仅以大小写进行区分

不能仅通过大小写区分命名空间、类型、成员和参数的标识符,因为针对公共语言运行时的语言不需要区分大小写。

CA1716:标识符不应与关键字冲突

某个命名空间名称或类型名称与编程语言中的保留关键字相同。 命名空间和类型的标识符不应与针对公共语言运行时的语言所定义的关键字冲突。

CA1801:检查未使用的参数

方法签名包含一个没有在方法体中使用的参数。

CA1804:移除未使用的局部变量

未使用的局部变量和不必要的赋值会增加程序集的大小并降低性能。

CA1809:避免过多的局部变量

优化性能的常见方法是将值存储于处理器寄存器,而不是内存中,这称为“注册值”。 若要提高所有的局部变量都能注册的可能性,应将局部变量的数目限制在 64 个以内。

CA1810:以内联方式初始化引用类型的静态字段

当一个类型声明显式静态构造函数时,实时 (JIT) 编译器会向该类型的每个静态方法和实例构造函数中添加一项检查,以确保之前已调用该静态构造函数。 静态构造函数检查会降低性能。

CA1811:避免使用未调用的私有代码

某个私有或内部(程序集级别)成员在程序集中没有调用方,既不是由公共语言运行时调用的,也不是由委托调用的。

CA1812:避免未实例化的内部类

程序集级别类型的实例不是由程序集中的代码创建的。

CA1813:避免使用未密封的特性

.NET Framework 类库提供用于检索自定义特性的方法。 默认情况下,这些方法搜索特性继承层次结构。 通过密封特性,将无需搜索继承层次结构,且能够提高性能。

CA1814:与多维数组相比,首选使用交错的数组

交错数组是元素为数组的数组。 构成元素的数组可以是不同的大小,以减少某些数据集的浪费空间。

CA1815:重写值类型上的 Equals 和相等运算符

对于值类型,Equals 的继承的实现使用反射库,并比较所有字段的内容。 反射需要消耗大量计算资源,可能没有必要比较每一个字段是否相等。 如果希望用户对实例进行比较或排序,或者希望用户将实例用作哈希表键,则值类型应实现 Equals。

CA1819:属性不应返回数组

即使属性是只读的,该属性返回的数组也不是写保护的。 若要使数组不会被更改,属性必须返回数组的副本。 通常,用户不能理解调用这种属性的负面性能影响。

CA1820:使用字符串长度测试是否有空字符串

使用 String.Length 属性或 String.IsNullOrEmpty 方法比较字符串要比使用 Equals 的速度快得多。

CA1821:移除空的终结器

应尽可能避免终结器,因为跟踪对象生存期会产生额外的性能系统开销。 空的终结器只会徒增系统开销,而没有一点好处。

CA1822:将成员标记为 static

可以将不访问实例数据或不调用实例方法的成员标记为 static(在 Visual Basic 中为 Shared)。 在将这些方法标记为 static 之后,编译器将向这些成员发出非虚拟调用站点。 这会使性能敏感的代码的性能得到显著提高。

CA1823:避免未使用的私有字段

检测到程序集内有似乎未访问过的私有字段。

CA2201:不要引发保留的异常类型

这使得很难检测和调试原始错误。

CA2205:使用 Win32 API 的托管等效项

定义了平台调用方法,但在 .NET Framework 类库中存在具有等效功能的方法。

CA2208:正确实例化参数异常

调用了异常类型 ArgumentException 或其派生类型的默认(无参数)构造函数,或者向异常类型 ArgumentException 或其派生类型的参数化构造函数传递了错误的字符串参数。

CA2211:非常量字段不应是可见的

不是常数也不是只读字段的静态字段不是线程安全的。 必须严格控制对这类字段的访问,并需要高级编程技术来同步对类对象的访问。

CA2217:不要使用 FlagsAttribute 标记枚举

外部可见的枚举使用 FlagsAttribute 标记,并且它包含的一个或多个值不是 2 的幂或不是为该枚举定义的其他值的组合。

CA2219:在异常子句中不引发异常

如果在 finally 或 fault 子句中引发异常,新异常将隐藏活动异常。 当在 filter 子句中引发异常时,运行时会在不提示的情况下捕捉异常。 这使得很难检测和调试原始错误。

CA2221:终结器应受到保护

终结器必须使用族访问修饰符。

CA2222:不要递减继承成员的可见性

不能更改所继承成员的访问修饰符。 将继承的成员更改为私有成员不能防止调用方访问该方法的基类实现。

CA2223:成员不应只是返回类型不同

虽然公共语言运行时允许使用返回类型区分其余部分都相同的成员,但该功能不包含在公共语言规范中,也不是各种 .NET 编程语言的共同功能。

CA2224:重载相等运算符时重写 Equals 方法

某公共类型实现了等号运算符,但是没有重写 Object.Equals。

CA2225:运算符重载具有命名的备用项

检测到运算符重载,但未找到预期的指定备用方法。 命名的备用成员提供了对与运算符相同的功能的访问,它提供给开发人员,在用不支持重载运算符的语言进行编程时使用。

CA2226:运算符应有对称重载

某个类型实现了相等运算符或不等运算符,却未实现相反运算符。

CA2227:集合属性应为只读

使用可写的集合属性,用户可以将该集合替换为不同的集合。 只读属性禁止替换该集合,但仍允许设置单个成员。

CA2230:对可变数量的参数使用 params

公共或受保护类型包含一个使用 VarArgs 调用约定(而不是 params 关键字)的公共或受保护方法。

CA2231:重写 ValueType.Equals 时应重载相等运算符

值类型重写 Object.Equals,但未实现相等运算符。

CA2234:传递 System.Uri 对象,而不传递字符串

调用了带有一个字符串参数的方法,该参数的名称中包含“uri”、“URI”、“urn”、“URN”、“url”或“URL”。 此方法的声明类型包含具有 System.Uri 参数的对应方法重载。

CA2239:为可选字段提供反序列化方法

类型有一个使用 System.Runtime.Serialization.OptionalFieldAttribute 特性标记的字段,并且该类型没有提供反序列化事件处理方法。