3

如果我编写以下代码:

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();
    }
}

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

4

1 回答 1

4

FxCop 10(随 Windows 7 和 .NET 4.0 SDK 提供)和 Code Analysis 2010(随 Visual Studio Premium 及更高版本提供)之间存在差异。Code Analysis 2010 有一组附加规则,其中包括高度改进的 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~

此外,围绕此规则还有一长串错误。该规则在 Visual Studio 2010 中进行了更改以触发更少的误报,但现在它有时会错过它应该标记的项目(并且会在以前的版本中标记)。没有足够的时间来修复 Visual Studio 2010 时间框架中的规则(检查错误报告评论)。

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

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

我创建了一个连接错误,要求将命名指南记录在规则文档中。

来自微软的评论:

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

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

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

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

于 2011-12-14T20:18:29.703 回答