FxCop(/ VS2010代码分析),可以将方法结果标记为IDisposable的“callers Respons now”吗?

时间:2011-12-12 10:12:05

标签: code-analysis idisposable fxcop chain-of-responsibility

如果我写下面的代码:

public void Execute()
{
    var stream = new MemoryStream();
    ...
}

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

  

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

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

是否有办法(例如使用属性)将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 个答案:

答案 0 :(得分:4)

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,不会标记Factory(因为规则现在看到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~,{{ 1}}。

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

随着即将推出的Roslyn编译器,Code Analysis可能会看到一次重大升级,直到那时才会有一些小的更新。 Visual Studio Dev11的当前版本不会触发您想要的位置。

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

我创建了一个connect bug,要求在the rules documentation中记录命名准则。

Microsoft的评论:

  

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

     

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

     

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

     

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