[置顶] 代码走查工具篇FxCop的规则总结与翻译_Part1

FxCop介绍

摘抄自百度知道,如下:

    FxCop是一个代码分析工具,它依照微软.NET框架的设计规范对托管代码assembly(可称为程序集assembly实际上指的就是.net中的.exe或者.dll文件(不包括netmodule文件),这种文件中包含四种信息:assembly的清单(包括引用外部的assemblynetmodule资源文件及包含在同一文件中的assembly);类型描述信息,包括版本信息与类的描述等;MSIL微软中间语言;资源(图标等))进行检查。它使用基于规则的引擎,来检查出你代码中不合规范的部分;你也可以定制自己的规则加入到这个引擎。这个工具微软免费提供。最新版需要.NET 2.0支持;此外,也有一个较老的针对.NET1.1的版本。

最新版FxCop使用一项叫做内窥(introspection,或称内观、内视)的技术,以窥探你的 assembly内部,而前一个版本则使用映射(reflection,或称反射)技术。这一点值得关注,因为使用上一个版本调试碰到问题你不得不停下 来,对代码作了任何更改之后都需要重新开始调试;而这些对于新版本都没有必要了。

大多数代码分析工具扫描你的源代码, 但是FxCop直接对你编译好的代码处理。.NET的每个assembly都有其metadata(可称为元数据,metadata是关于一个 assembly中各元素的类型信息库,它本身也存放在这个assembly),它对assembly以及assembly内用到的所有类型进行描述。 FxCop会使用这个metadata以获知代码内部的运行状况。另外,它也对代码编译时生成的MSILMicrosoft Intermediate Language,微软中间语言)进行检查。

通过对metadataMSIL检查的结合,FxCop可以得出大量信息,以此获得对代码执行时所作所为的理解。它把你的代码和各条规则逐一比较检查,在每一个实例中,当找到不符合规则的代码时就生成一条消息。

 

FxCop Rule 翻译

 

一、Design Rules(设计规约)

1AbstractTypesShouldNotHaveConstructors    CA1012

不言而喻,抽象类型里即使编写了构造函数也不能直接的调用到。

2AssembliesShouldHaveValidStrongNames   CA2210

    程序集应该有强类型签名,强名称可避免客户端在不知情的情况下加载已被篡改的程序集。 除非极为有限的几种情况,否则不应部署没有强名称的程序集。

3AvoidEmptyInterfaces    CA1040

避免空的接口,如果设计中包含类型需要实现的空接口,可以将接口作为标记或者作为标识一组类型的手段使用。如果此标识在运行时出现,则实现这种应用的正确方式是使用自定义特性。通过是否使用特性,或使用特性的属性,可以标识目标类型。如果该标识必须在编译时出现,则使用空接口是可以接受的。 

4AvoidExcessiveParametersOnGenericTypes    CA1005

避免泛型类型的参数过多,两个是一个分界线,最好不要超过两个。

5AvoidNamespacesWithFewTypes    CA1020

   避免使用类型极少的命名空间,合理的归类命名空间可以提高代码的易维护及易读性。

6AvoidOutParameters   CA1021

   尽量避免使用out参数,但也要分情况。举例微软的try模式的方式

7CollectionsShouldImplementGenericInterface   CA1010

    集合应该实现泛型接口,常见的泛型接口为:            System.Collections.Generic.IEnumerable<T>

System.Collections.Generic.ICollection<T>

System.Collections.Generic.IList<T>

8ConsiderPassingBaseTypesAsParameters   CA1011

某方法声明包含一个派生类型的形参,且该方法仅调用该参数的基类型的成员的时候参数要定义成基类型,这样这个方法使用面会更广,任何这个基类的子类都可以当做实参传进来。

9DeclareEventHandlersCorrectly   CA1009  

正确声明事件处理程序,举一个自己写的小例子:

using System;
using System.Windows.Forms;
namespace TestFxCopRule
{
     public class AlarmEventArgs : EventArgs {
        public AlarmEventArgs(string myName, int myAge) {
            this.MyName = myName;
            this.MyAge = myAge;
    }
        private AlarmEventArgs()
        {}
        public string MyName;
        public int MyAge;
    }
   public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
    public class MyEvent
    {
        public AlarmEventHandler DDD;
        public MyEvent()
        {
            DDD+= dd;
        }
        public void InvokeMyEvent()
        {
            if(DDD==null)
            {
                return;
            }
            AlarmEventArgs e=new AlarmEventArgs("Anders lu",28);
            DDD(this,e);
        }
        public void  dd (object sender, AlarmEventArgs e)
        {
            MyEvent mye=sender as MyEvent;
            MessageBox.Show(e.MyName+" Invoke MyEvent  in  "+ mye.GetType().ToString() );
        }
    }
}

DeclareTypesInNamespaces   CA1050 

应在命名空间内声明类型以避免名称冲突,并作为一种在对象层次结构中组织相关类型的方式。位于任何命名的命名空间之外的类型属于全局命名空间,全局命名空间无法在代码中引用。 

11DefaultParametersShouldNotBeUsed   CA1026

为了使.net代码应用面更广,建议不要使用默认参数,如果有这方便的需求可以采取提供默认参数的方法重载来替换使用默认参数的方法 

DefineAccessorsForAttributeArguments   CA1019

定义特性参数的访问器,请为每一个不具有只读属性的构造函数参数添加只读属性。 

DoNotCatchGeneralExceptionTypes  CA1031 

尽量不要捕捉一般性异常,要尽量具体话异常

DoNotDeclareProtectedMembersInSealedTypes CA1047 

不要在密封类型中声明受保护的成员,按照定义,不能从密封类型继承,意味着不能调用密封类型上受保护的方法。 

15DoNotDeclareStaticMembersOnGenericTypes  CA1000

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

16DoNotDeclareVirtualMembersInSealedTypes CA1048

 不要在密封类型中声明虚拟成员,类型将方法声明为虚方法,使继承类型可以重写虚方法的实现。根据定义,不能从密封类型继承,这使得密封类型上的虚方法没有意义。 

17DoNotDeclareVisibleInstanceFields  CA1051

不要声明可见实例字段,字段的主要用途应是作为实现的详细信息。字段应为 private 或 internal,并应当通过使用属性来公开。访问属性和访问字段一样容易,且随着类型的功能扩展,无需引入间断更改即可更改属性的访问器中的代码。仅返回私有或内部字段值的属性经过优化,可以像访问字段那样执行;在属性上使用外部可见字段不太会提高性能。 

18DoNotExposeGenericLists  CA1002

不要公开泛型列表,System.Collections.Generic.List<T> 是针对性能(而非继承)设计的泛型集合。 System.Collections.Generic.List<T> 不包含更便于更改继承类的行为的虚拟成员。下面的泛型集合是针对继承功能设计的,应公开为 System.Collections.Generic.List<T> 以外的内容。

System.Collections.ObjectModel.Collection<T>

System.Collections.ObjectModel.ReadOnlyCollection<T>

System.Collections.ObjectModel.KeyedCollection<TKey, TItem>

19DoNotHideBaseClassMethods  CA1061

不要隐藏基类方法,如果派生方法的参数签名只是在类型方面有所不同,而且与基方法的参数签名中的对应类型相比,这些类型的派生方式更弱,则基类型中的方法将被派生类型中的同名方法隐藏。 

  20DoNotNestGenericTypesInMemberSignatures CA1006

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

21DoNotOverloadOperatorEqualsOnReferenceTypes  CA1046

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

22DoNotPassTypesByReference   CA1045

不要通过引用来传递类型, 传递引用类型需要两个关键字out与ref,语法较难理解,如无特殊用途,不采取此语法。

23DoNotRaiseExceptionsInUnexpectedLocations  CA1065

不要在意外的位置引发异常,不应引发异常的方法可分为以下几类:

Property Get 方法;事件访问器方法;Equals 方法;GetHashCode 方法ToString 方法;静态构造函数;终结器;Dispose 方法;相等运算符;隐式转换运算符。

24EnumStorageShouldBeInt32 CA1028

枚举存储应为 Int32,使用示例如下:

 [Flags]

    public enum Days : int

    {

        None        = 0,

        Monday      = 1,

        Tuesday     = 2,

        Wednesday   = 4,

        Thursday    = 8,

        Friday      = 16,

        All         = Monday| Tuesday | Wednesday | Thursday | Friday

    }

EnumeratorsShouldBeStronglyTyped CA1038

枚举数应强类型化,此规则要求 IEnumerator 实现还提供 Current 属性的强类型版本,以使用户在使用该接口提供的功能时不必将返回值强制转换为强类型。该规则假定实现 IEnumerator 的类型包含强于 Object 的类型的实例集合。 

25EnumsShouldHaveZeroValue  CA1008

枚举后选址里必须包含零值,像其他值类型一样,未初始化枚举的默认值为零。无标志特性的枚举应定义值为零的成员,这样默认值即为该枚举的有效值。如果合适,将该成员命名为“None”。否则,将零赋给最常用的成员。请注意,默认情况下,如果声明中未设置第一个枚举成员的值,则其值为零。

如果应用了 FlagsAttribute 的枚举定义零值成员,则其名称应为“None”,以指示枚举中尚未设置值。出于任何其他目的使用零值成员都与使用 FlagsAttribute 的目的相背,因为 AND 和 OR 按位运算符对该成员无用。这意味着,只能为一个成员赋值零。请注意,如果应用了标志特性的枚举中发生多个零值的成员,则 Enum.ToString() 会为非零成员返回不正确结果。

26ExceptionsShouldBePublic CA1064

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

27GenericMethodsShouldProvideTypeParameter CA1004

泛型方法应提供类型参数,下面的示例演示了调用两个泛型方法的语法。 InferredTypeArgument 的类型参数是推断出来的,而 NotInferredTypeArgument 的类型参数则必须是显式指定的。

using System;

namespace DesignLibrary

{

   public class Inference

   {

      // This method violates the rule.

      public void NotInferredTypeArgument<T>()

      {

         Console.WriteLine(typeof(T));

      }

      // This method satisfies the rule.

      public void InferredTypeArgument<T>(T sameAsTypeParameter)

      {

         Console.WriteLine(sameAsTypeParameter);

      }

   }

   class Test

   {

      static void Main()

      {

         Inference infer = new Inference();

         infer.NotInferredTypeArgument<int>();

         infer.InferredTypeArgument(3);

      }

   }

}

 

28ICollectionImplementationsHaveStronglyTypedMembers  CA1035

ICollection 实现含有强类型成员,此规则要求 ICollection 实现提供强类型成员,以使用户在使用该接口提供的功能时不必将参数强制转换成 Object 类型。该规则假定实现 ICollection 的类型执行此操作来管理强于 Object 的类型的实例集合。

ICollection 实现 System.Collections.IEnumerable 接口。如果集合中的对象扩展了 System.ValueType,则您必须为 GetEnumerator 提供一个强类型成员,以避免由装箱造成的性能下降。当集合的对象是引用类型时,这是不需要的。

要实现接口成员的强类型版本,请使用 InterfaceName.InterfaceMemberName 形式的名称(如 CopyTo)来显式实现接口成员。这些显式接口成员使用由该接口声明的数据类型。使用接口成员名称(如 CopyTo)来实现强类型成员。将强类型成员声明为公共的,将参数和返回值声明为由集合管理的强类型。这些强类型会替换由接口声明的较弱类型,例如 Object 和 Array

29ImplementIDisposableCorrectly  CA1063

正确实现 IDisposable

30ImplementStandardExceptionConstructors  CA1032

实现标准异常构造函数,异常类型必须实现下列构造函数:

公共 NewException()

公共 NewException(string)

公共 NewException(string, Exception)

受保护或私有的 NewException(SerializationInfo, StreamingContext)

如果不能提供完整的构造函数集,要正确处理异常将变得比较困难。例如,带有签名 NewException(string, Exception) 的构造函数用于创建由其他异常导致的异常。如果没有此构造函数,则无法创建和引发包含内部(嵌套)异常的自定义异常的实例,而在此类情况下托管代码应执行此操作。按照约定,前三个异常构造函数是公共的。第四个构造函数在未密封类中是受保护的,而在密封类中是私有的。

31IndexersShouldNotBeMultidimensional  CA1023

索引器不应是多维的,索引器(即索引属性)应该使用一个索引。多维索引器会大大降低库的可用性。如果设计需要使用多个索引,请重新考虑类型是否代表逻辑数据存储。否则,请使用方法。

32InterfaceMethodsShouldBeCallableByChildTypes  CA1033

接口方法应可由子类型调用,请考虑显式实现公共接口方法的基类型。从该基类型派生的类型只能通过对被强制转换为接口的当前实例(C# 中的 this)的引用来访问继承的接口方法。如果派生的类型重新实现(显式)继承的接口方法,则无法再访问基实现。通过当前实例引用进行的调用将调用派生的实现;这会导致递归调用,并最终导致堆栈溢出。 

33ListsAreStronglyTyped  CA1039

列表提供强类型成员,此规则要求 IList 实现提供强类型成员,以使用户在使用该接口提供的功能时不必将参数强制转换成 System.Object 类型。 IList 接口由可以通过索引访问的对象集合实现。该规则假定实现 IList 的类型这样做以管理类型比 Object 更强的实例的集合。 

34MarkAssembliesWithAssemblyVersion   CA1016 

用 AssemblyVersionAttribute 标记程序集

35MarkAssembliesWithClsCompliant CA1014

用 CLSCompliantAttribute 标记程序集

36MarkAssembliesWithComVisible  CA1017 

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

37MarkAttributesWithAttributeUsage CA1018 

可通过在特性类上放置 AttributeUsageAttribute 来控制特性类的使用方式。

38MarkEnumsWithFlags  CA1027

Flage特性标记枚举。

39MembersShouldNotExposeCertainConcreteTypes CA1059

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

40MovePInvokesToNativeMethodsClass  CA1060

将 P/Invoke 移动到 NativeMethods 

41NestedTypesShouldNotBeVisible  CA1034

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

42OverloadOperatorEqualsOnOverloadingAddAndSubtract CA1013

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

43OverrideMethodsOnComparableTypes  CA1036

     重写可比较类型中的方法定义自定义排序顺序的类型实现 IComparable 接口。  CompareTo 方法返回一个整数值,指示该类型的两个实例的正确排序顺序。  该值标识设置排序顺序的类型;这意味着不会应用相等、不等、小于或大于的常规含义。  提供 IComparable 的实现时,通常还必须重写 Equals,以使其返回与 CompareTo 一致的值。  如果重写 Equals 并使用支持运算符重载的语言编写代码,则还应提供与 Equals 一致的运算符。 

44PropertiesShouldNotBeWriteOnly  CA1044

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

45ProvideObsoleteAttributeMessage  CA1041

    提供 ObsoleteAttribute 消息ObsoleteAttribute 用于标记被否决的库类型和成员。  库使用者应避免使用任何标记为已过时的类型或成员。  这是因为它可能不被支持,并将最终将从库的更高版本中被删除。  当编译用 ObsoleteAttribute 标记的类型或成员时,将显示特性的 Message 属性。  这将为用户提供有关已过时的类型或成员的信息。  该信息通常包括库设计器还将支持已过时类型或成员的时间长度,以及首选的替代类型或成员。 

46ReplaceRepetitiveArgumentsWithParamsArray  CA1025

用形参数组替换重复的实参公共类型中的某个公共或受保护方法具有三个以上的参数,且其后三个参数为相同类型

47StaticHolderTypesShouldBeSealed  CA1052

该规则假定只包含静态成员的类型没有设计为能被继承,因为该类型不提供可以在派生类型中重写的任何功能。  不希望被继承的类型应使用 sealed 修饰符禁止将其用作基类型。 

48StringUriOverloadsCallSystemUriOverloads  CA1057

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

49TypesShouldNotExtendCertainBaseTypes  CA1058

类型不应扩展某些基类型外部可见的类型扩展某些基类型。  目前,此规则报告从下列类型派生的类型: 

System.ApplicationException 

System.Xml.XmlDocument 

System.Collections.CollectionBase 

System.Collections.DictionaryBase 

System.Collections.Queue 

System.Collections.ReadOnlyCollectionBase 

System.Collections.SortedList 

System.Collections.Stack 

50TypesThatOwnDisposableFieldsShouldBeDisposable    CA1001

     具有可释放字段的类型应该是可释放的

51TypesThatOwnNativeResourcesShouldBeDisposable  CA1049

    拥有本机资源的类型应是可释放的

52UriParametersShouldNotBeStrings   CA1054

    URI 参数不应为字符串

53UriPropertiesShouldNotBeStrings  CA1056 

  URI属性不应为字符串

54UriReturnValuesShouldNotBeStrings  CA1055

 URI返回值不应为字符串

55UseEventsWhereAppropriate  CA1030

  在适当的时机下使用事件, 该规则检测名称通常用于事件的方法。  事件遵循观察者发布-订阅设计模式;当需要与其他对象交流一个对象的状态更改时使用这些事件。  如果为响应明确定义的状态更改而调用一个方法,则应由事件处理程序调用该方法。  调用该方法的对象应引发事件而不是直接调用该方法。 

在单击按钮等用户操作会导致执行一段代码的用户界面应用程序中,可以找到事件的某些常见示例。  .NET Framework 事件模型不限于用户界面;可以在必须与一个或多个对象交流状态更改的任意位置使用它。 

56UseGenericEventHandlerInstances  CA1003 

使用通用的事件Handler

57UseGenericsWhereAppropriate  CA1007 

     在适当时机使用泛型。引用参数是用 ref(在 Visual Basic 中为 ByRef)关键字修饰的参数。为引用参数提供的参数类型必须与引用参数类型完全匹配。若要使用从引用参数类型派生的类型,必须首先对该类型进行强制转换,然后将该类型分配给引用参数类型的变量。使用泛型方法使受约束的所有类型都可以传递给方法,而无需先将类型强制转换为引用参数类型。

58UseIntegralOrStringArgumentForIndexers  CA1043

将整型或字符串参数用于索引器  索引器(即索引属性),应将整型或字符串类型用于索引。这些类型一般用于为数据结构创建索引和提高库的可用性。Object 类型的使用应仅限于不能在设计时指定特定整型或字符串类型的那些情况。如果设计需要对索引使用其他类型,请重新考虑该类型是否代表逻辑数据存储区。如果该类型不代表逻辑数据存储区,请使用方法。

59UsePropertiesWhereAppropriate CA1024

 在适当的时机使用属性,在大多数情况下,属性代表数据,而方法执行操作。  访问属性的方式与访问字段的方式相似,因此使用它们更容易。  如果存在下列条件之一,方法就很适于成为属性: 

不采用任何参数并返回对象的状态信息

接受单个参数来设置对象的部分状态

属性的表现应当与字段一样;如果该方法不是这样,则不应将其更改为属性。  在下列情况下,方法比属性更好 

方法执行耗时的操作。  与设置或获取字段值所需的时间相比,此方法的速度明显较慢

方法执行转换。  访问字段不会返回它所存储的数据的转换版本

Get 方法会产生明显副作用。  检索字段的值不会产生任何副作用 

执行的顺序很重要。  设置字段的值并不依赖于其他操作的发生 

连续调用两次方法会产生不同的结果

方法是静态的,但返回了调用方可更改的对象。  调用方不能通过检索某字段的值来更改该字段存储的数据

方法返回数组


 

 

 

 

你可能感兴趣的:(part)