FxCop(/VS2010 代码分析),可以将方法结果标记为 IDisposable 的“现在调用者责任”吗?

Posted

技术标签:

【中文标题】FxCop(/VS2010 代码分析),可以将方法结果标记为 IDisposable 的“现在调用者责任”吗?【英文标题】:FxCop (/VS2010 Code Analysis), possible to flag method result as "callers responsibility now" for IDisposable? 【发布时间】:2011-12-12 10:12:05 【问题描述】:

如果我写如下代码:

public void Execute()

    var stream = new MemoryStream();
    ...

然后代码分析会将其标记为:

警告 1 CA2000:Microsoft.Reliability:在方法“ServiceUser.Execute()”中,在对对象“流”的所有引用超出范围之前调用 System.IDisposable.Dispose。 C:\Dev\VS.NET\DisposeTest\DisposeTest\ServiceUser.cs 14 DisposeTest

但是,如果我创建工厂模式,我仍然可能需要处理对象,但现在 FxCop/代码分析不会抱怨。 相反,它抱怨的是工厂方法,而不是调用它的代码。 (我想我有一个确实抱怨工厂方法的例子,但我在这里发布的那个没有,所以我把它删掉了)

有没有办法(例如使用属性)将 IDisposable 对象的职责从工厂方法转移到调用者身上?

获取此代码:

public class ServiceUser

    public void Execute()
    
        var stream = StreamFactory.GetStream();
        Debug.WriteLine(stream.Length);
    


public static class StreamFactory

    public static Stream GetStream()
    
        return new MemoryStream();
    

在这种情况下,没有警告。我希望 FxCOP/CA 仍然抱怨我原来的方法。处理那个对象仍然是我的责任。

有什么方法可以告诉 FxCOP/CA?例如,我最近冒险研究了 ReSharper 提供的注释属性,以便告诉它的分析引擎信息,否则它无法理解。

所以我设想这样的事情:

public static class StreamFactory

    [return: CallerResponsibility]
    public static Stream GetStream()
    
        return new MemoryStream();
    

或者这种设计方式有问题?

【问题讨论】:

【参考方案1】:

FxCop 10(随 Windows 7 和 .NET 4.0 SDK 提供)和 Code Analysis 2010(随 Visual Studio Premium 及更高版本提供)之间存在差异。 Code Analysis 2010 有一个set of additional rules,其中包括高度改进的 IDisposable 规则版本。

使用 Visual Studio Premium 下的 Code Analysis 2010,工厂不会被标记(因为规则现在看到 IDisposable 变量返回到调用方法)。但是,由于规则的极端情况例外之一,接收方法也没有被标记。有一个方法名称列表会触发规则。如果将GetStream 方法重命名为CreateStream,规则会突然触发:

Warning 4   CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()',
call System.IDisposable.Dispose on object 'stream' before all references to it are out
of scope.   BadProject\Class1.cs    14  BadProject

我无法找到有效的方法前缀列表。我已经尝试了一些,Create~Open~ 触发了规则,许多其他你可能希望工作的,不要,包括Build~Make~Get~

另外还有一个long list of bugs surrounding this rule。该规则在 Visual Studio 2010 中进行了更改以触发更少的误报,但现在它有时会错过它应该标记的项目(并且会在以前的版本中标记)。没有足够的时间来修复 Visual Studio 2010 时间框架中的规则(查看错误报告 cmets)。

随着即将推出的 Roslyn 编译器,代码分析可能会出现重大升级,在此之前,预计只会有少量更新。 Visual Studio Dev11 的当前版本不会触发您想要的位置。

所以总结一下,没有你的属性不会有太大帮助,因为规则已经检测到你正在传递 IDisposable 作为返回值。因此,代码分析知道在返回之前将其处理掉是不好的。如果您使用的是未记录的命名规则,则会触发该规则。也许属性可以扩展命名规则,但我宁愿让微软真正修复实际规则。

我创建了一个connect bug 请求将命名指南记录在the rules documentation 中。

来自微软的评论:

Microsoft 于 2012 年 1 月 19 日上午 10:41 发布 你好,

感谢您抽出宝贵时间对此进行调查并提交文档更新请求。但是,在与我们的文档团队讨论后,我们决定不按照您的要求记录命名约定。

正如您在 *** 线程中指出的那样,该规则历来存在很多可靠性问题,并且关闭名称是为了减少误报数量而添加的内部实现细节。然而,这并不是关于开发人员应该如何命名他们的方法的说明性指南,它是在对常见编码实践进行调查后添加的。我们认为,长期的解决办法是提高规则的可靠性,而不是根据内部实施细节将命名指南添加到我们的公共文档中,这些细节将随着规则的改进而不断变化。

最好的问候, Visual Studio 代码分析团队

【讨论】:

以上是关于FxCop(/VS2010 代码分析),可以将方法结果标记为 IDisposable 的“现在调用者责任”吗?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以将 PhoenixAnalysis Engine 与 FxCop 10 一起使用?

VS2008中的代码分析(FxCop)功能在哪里?

Fxcop 针对 VS 2010 设计的自定义代码不适用于 VS 2012

VS2010 自定义代码分析规则

是否可以在未安装 VS 的情况下从 MSBuild 命令行运行 FxCop 代码分析?

使用 FxCop 获得百分比代码覆盖率