告诉FxCop另一种方法是调用dispose

Haa*_*ked 14 c# fxcop idisposable

通常,当您处置私有成员时,您可能会执行以下操作:

public void Dispose() {
    var localInst = this.privateMember;
    if (localInst != null) {
        localInst.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

本地赋值的目的是避免竞争条件,其中另一个线程可能在null检查后将私有成员分配为null.在这种情况下,我不关心是否Dispose在实例上调用两次.

我一直使用这种模式,所以我写了一个扩展方法来做到这一点:

public static void SafeDispose(this IDisposable disposable)
{
    if (disposable != null)
    {
        // We also know disposable cannot be null here, 
        // even if the original reference is null.
        disposable.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在我的班上,我可以这样做:

public void Dispose() {
    this.privateMember.SafeDispose();
}
Run Code Online (Sandbox Code Playgroud)

问题是,FxCop不知道我这样做了它给了我CA2000:在每种情况下丢失范围警告之前处理对象.

我不想关闭这个规则,我不想压制每一个案例.有没有办法提示FxCop这个方法相当于Dispose它的相关程度?

Tra*_*lig 8

简短的回答是:没有办法暗示物体被放置在别处.

一点点Reflector-ing(或dotPeek-ing,或其他)解释了原因.

FxCop在C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop.(根据您的OS/VS版本组合进行相应调整.)规则位于Rules子目录中.

在主FxCop文件夹中,打开

  • Microsoft.VisualStudio.CodeAnalysis.dll
  • Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll
  • phx.dll

Rules文件夹中,打开DataflowRules.dll.

DataflowRules.dll找到Phoenix.CodeAnalysis.DataflowRules.DisposeObjectsBeforeLosingScope.这是进行评估的实际班级.

查看那里的代码,您可以看到与您的问题有关的两件事.

  1. 它使用一个名为的共享服务SharedNeedsDisposedAnalysis.
  2. 源于FunctionBodyRule.

第一个项目很有趣,因为SharedNeedsDisposedAnalysis它决定了哪些符号需要Dispose()调用.它非常彻底,通过代码"行走"来确定需要处理什么以及实际处置的内容.然后它会保存这些东西的表格供以后使用.

第二个项目很有趣,因为FunctionBodyRule规则评估单个函数的主体.还有其他规则类型,比如FunctionCallRule评估函数调用成员之类的东西(例如,ProvideCorrectArgumentsToFormattingMethods).

关键是,在该SharedNeedsDisposedAnalysis服务中潜在的"未命中"之间,它可能不会通过您的方法递归,以确定事物实际上已经被处理,并且限制FunctionBodyRule不超出功能体,它只是没有捕获您的扩展.

这就是"保护函数" Guard.Against<ArgumentNullException>(arg)在使用之前永远不会被视为验证参数的原因相同- FxCop仍然会告诉您检查参数是否为null,即使这就是"保护函数"正在做的事情.

你基本上有两个选择.

  1. 排除问题或关闭规则.没有办法做你想做的事.
  2. 创建将了解扩展方法的自定义/派生规则.使用自定义规则代替默认规则.

在自己编写了自定义FxCop规则之后,我会告诉您我发现它... 非平凡.如果你确实走了这条路,虽然世界上的建议是使用新的凤凰引擎规则样式(这是当前DisposeObjectsBeforeLosingScope使用的),我发现更容易理解旧的/标准的FxCop SDK规则(参见FxCopSdk.dll主要内容) FxCop文件夹).反射器对于弄清楚如何做到这一点将是一个巨大的帮助,因为它上面几乎没有文档.查看Rules文件夹中的其他程序集以查看这些示例.