c# - 为什么 FxCop 不为这种未处置类实例的微不足道的情况报告 CA2000?

标签 c# code-analysis fxcop

以下代码生成 CA2000 ("Dispose objects before losing scope") Main 的第一行违规,但不是第二行。我真的很喜欢第二行的 CA2000 违规,因为这是一个(明显简化的)模式,经常在我处理的大型代码库中找到。

有谁知道为什么不为第二行产生违规?

public static void Main()
{
    new Disposable();
    MakeDisposable();
}

private static Disposable MakeDisposable() { return new Disposable(); }

private sealed class Disposable : IDisposable
{
    public void Dispose()
    {
    }
}

最佳答案

简短的回答是,CA2000 坏了,不太可能很快修好。参见 this bug report这几乎正​​是你的问题:

The warning CA2000 in particular is a rule that has known issues and that we won’t be able to fix it up in its current form.


较长的答案是,使 CA2000 正确是困难。在过去的 Visual Studio 版本中,尤其是 2010 版,错误的 CA2000 警告无处不在,您无法采取任何措施让它们消失。在 Stack Overflow 上搜索有关它的数十个问题中的任何一个。

即使在您可以消除警告的情况下,解决方法也比只保留它更糟糕。问题是,在您遇到的这种情况下,您希望对象在离开工厂方法的范围之前被处理掉。除非,你这样做 - 如果它抛出异常。在这种情况下,方法的返回值丢失,调用者无法自行处置对象。

不幸的是,试图弄清楚这一点意味着对已编译的 IL 进行程序流分析,以确定是否有任何代码路径(包括异常代码路径)允许对象泄漏。最终结果是,几乎所有您尝试从方法返回 IDisposable 的情况都会产生错误。

Microsoft 通过做两件事对此做出回应:

  • 调低 CA2000 的灵敏度,使其仅在最明显的情况下触发。这似乎是合理的,因为像您的第一行这样明显的情况比更隐蔽的情况更有可能是错误,并且更容易修复。
  • 将 CA2000 从他们推荐的代码分析规则中剔除;请注意,他们的“扩展正确性”规则集不再包括 CA2000。

随着 Roslyn 编译器的重写,FxCop 等工具能够进行一些源代码级分析,在这种情况下可能更容易正确。同时,普遍的共识是,只需关闭 CA2000。


如果您好奇的话,一些测试似乎可以确认当前 (2013) CA 规则在本地包含、本地构造的 IDisposable 实例时触发> 超出范围。 IOW,该对象不能离开您新建它的方法,否则 CA 会忽略它。这让我相信 CA 根本没有深入研究方法调用来进行分析。除了试图消除误报之外,它还可能是通过取消一些昂贵的检查来加快 CA 流程的整体尝试的一部分,我认为这发生在 2010 年到 2012 年之间?

如果我在您的示例中添加一点,您可以看到明显的模式,其中哪些收到警告:

class Program
{
    public static void Main()
    {
        new Disposable(); // CA2000

        IDisposable x;
        MakeDisposable(out x);

        Test();
    }

    public static Disposable Test()
    {
        IDisposable z;
        var x = MakeDisposable(out z);
        var y = new Disposable(); // CA2000
        return x;
    }

    private static Disposable MakeDisposable(out IDisposable result)
    {
        result = new Disposable();

        new Disposable(); // CA2000
        return new Disposable(); 
    }
} 

关于c# - 为什么 FxCop 不为这种未处置类实例的微不足道的情况报告 CA2000?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29594148/

相关文章:

C# 代码分析 CA1822 警告 - 为什么?

version-control - 各个代码部分的 TFS 2010 更改历史记录

c# - 您最喜欢的 FxCop 规则是什么?

c# - 如何在 EF Core 中创建 DbContext 实例时传递 DbContextOptions 值

c# - 创建在所有进程之间共享状态的多进程架构的最轻量级解决方案是什么

sql - 将可为 Null 的列传递给函数会导致警告 SR0007 - 即使函数内部使用 COALESCE 和 ISNULL

c# - 为什么 FxCop 警告此 C# 代码中的溢出 (CA2233)?

c# - CA1500 与 SA1309 - 哪一个获胜?

c# - 如何将多个 MVC.net 应用程序与其他 MVC.net 应用程序连接?

c# - 事件处理程序和接口(interface)