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

Zvo*_*nko 15 c# dispose fxcop static-analysis

我在项目中使用静态代码分析来检查代码违规.其中一个广泛使用的规则是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
}
Run Code Online (Sandbox Code Playgroud)

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

Han*_*ant 5

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

CA2213应处理一次性字段
“错误”包含<Font>k__BackingFieldIDisposable类型的字段:“字体”。将“不良”上的Dispose方法更改为在此字段上调用Dispose或Close。

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

这类问题需要源代码分析,而不是当前实施的IL分析。机会来了,如今,使用Roslyn可以更轻松地实现源代码分析。VS2015是第一个支持“实时代码”分析的VS版本。我尚不知道它是否会很快发现CA2213样式错误。


Din*_*eyn 0

静态分析工具经过调整,可以在生成太多误报(即在完美的代码上发出问题)和太多漏报(即在代码中遗漏真正的问题)之间进行良好的权衡。

让我们举一个简单的例子:

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

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

现在,让我们把事情变得稍微复杂一些:

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

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

using (var p = new MemoryStream())
{
    using (var x = FieldIsInjected(p)) { /* ... */ }
} // p is properly disposed
Run Code Online (Sandbox Code Playgroud)

通常,确切的行为(包括所有极端情况的处理)不会被记录下来,因为随着时间的推移,详尽的文档的维护成本太高。例如,https://msdn.microsoft.com/en-us/library/ms182328.aspx中明确提到了此异常