CA2213代码分析规则和自动实现的属性

时间:2014-10-29 07:44:35

标签: c# dispose static-analysis fxcop

我在项目中使用静态代码分析来检查代码违规。其中一个广泛使用的规则是CA2213,它检查一次性场的正确处理。

我注意到CA2213没有检查处理自动实现的属性。

此外,如果类继承自实现IDisposable的类并且不覆盖Dispose方法,则CA2213不会检查是否处置既不是字段也不是自动实现的属性。

实际例子:

public sealed class Good : IDisposable {
    private Font font;
    public Font Font {
        get { return font; }
        set { font = value; }
    }
    public Good() { font = new Font("Arial", 9); }
    public void Dispose() { /* Do nothing */ }       // CA2213
}

public sealed class Bad : IDisposable {
    public Font Font { get; set; }
    public Bad() { Font = new Font("Arial", 9); }
    public void Dispose() { /* Do nothing */ }       // No warning
}

还有其他人遇到过这种行为吗?这是CA2213规则中的设计还是错误?

4 个答案:

答案 0 :(得分:4)

代码分析器确实有局限性,此代码中的代码分析器需要生成可操作的警告。一个程序员可以实际跟进来修复他的代码。当前代码分析器的一个关键问题是它不分析源代码,它可以从编译器生成的程序集中工作。哪个好,适用于任何.NET语言。但没有人会喜欢这个警告:

  

CA2213应处置一次性字段
  &#39;坏&#39;包含IDisposable类型的字段<Font>k__BackingField:&#39;字体&#39;。在&#39; Bad&#39;上更改Dispose方法在此字段上调用Dispose或Close。

Yikes,当然程序中没有这样的字段。为了生成更好的消息,分析器必须确定元数据中的<Font>k__BackingField字段实际上与自动实现的Font属性相关联。元数据中没有任何内容可以明确地建立连接。该字段仅携带[CompilerGenerated]属性,自动生成的字段名称是编译器实现细节。不同的语言编译器生成不同的名称。

这是一种需要源代码分析的问题,而不是目前实施的IL分析。机会正在敲门,今天Roslyn可以更容易地实现源代码分析。 VS2015是第一个支持&#34; Live Code&#34;的VS版本。分析。我不知道它是否会很快找到CA2213样式错误。

答案 1 :(得分:0)

静态分析工具经过精心调整,可以在生成过多的误报(即在完美的代码上发出问题)和过多的假阴性(即代码中缺少实际问题)之间进行良好的权衡。

我们举一个简单的例子:

// CA2213 detects an issue
class OwnsTheField : IDisposable
{
    private MemoryStream f = new MemoryStream();
    public void Dispose() {}
}

在这种情况下很明显应该报告一个问题,事实确实如此。

现在,让我们稍微复杂一点:

// CA2213 does not detect
class FieldIsInjected : IDisposable
{
    private MemoryStream f;
    public FieldIsInjected(MemoryStream p)
    {
        f = p;
    }
    public void Dispose() { }
}

在这种情况下,可能不存在不处理f的问题。如果调用者正确处理p,那么一切都按预期工作:

using (var p = new MemoryStream())
{
    using (var x = FieldIsInjected(p)) { /* ... */ }
} // p is properly disposed

通常情况下,不会记录确切的行为(包括处理所有极端情况),因为详尽的文档在一段时间内维护成本太高。例如,https://msdn.microsoft.com/en-us/library/ms182328.aspx

中明确提到了此异常

答案 2 :(得分:0)

规则来自.net framework 2auto properties are from C# 3,它是在创建规则后添加到语言规范中的。规则是根据字段而不是属性来定义的,因此它似乎应该更新,但是按照当前指定的方式工作。

This Question on disposing properties似乎表明实现IDisposable的属性在框架中不一致。

答案 3 :(得分:0)

分析引擎完全能够在物业及其支持场之间行走。它只是没有逻辑去做,因此错过了发出警告的机会。更糟糕的是,如果正确处置的属性是get-only,则会发出false warning