C# 私人无效处置(bool)?

C# 私人无效处置(bool)?,c#,code-analysis,idisposable,fxcop,C#,Code Analysis,Idisposable,Fxcop,在一些地方,人们建议对IDisposable模式使用private void Dispose(bool)。但这似乎已经过时(至少对于未密封的类而言),因为新建议的模式(根据Microsoft)是受保护的虚拟void Dispose(bool) 问题是,代码分析不会报告违反的私有void Dispose(bool),即使它似乎直接违反了模式 这是怎么回事?private void Dispose(bool)是否以某种方式被调用(或编译成类似于protected virtual Dispose(bo

在一些地方,人们建议对
IDisposable
模式使用
private void Dispose(bool)
。但这似乎已经过时(至少对于未密封的类而言),因为新建议的模式(根据Microsoft)是
受保护的虚拟void Dispose(bool)

问题是,代码分析不会报告违反的私有void Dispose(bool),即使它似乎直接违反了模式

这是怎么回事?
private void Dispose(bool)
是否以某种方式被调用(或编译成类似于
protected virtual Dispose(bool)

如果这是代码分析中的一些问题,并且是错误的模式,那么有没有方法检测到这一点?可能是通过StyleCop

编辑:经过考虑,是否基类可以调用
base.Dispose()
,这将命中
私有void Dispose(bool)
?即使它不能传入参数

编辑:样本

public class A : IDisposable
{
    ~A()
    {
        this.Dispose(false);
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing) // Should be protected virtual void Dispose(bool)
    {
        Console.WriteLine("A");
    }
}

public class B : A
{
    protected virtual void Dispose(bool disposing) // Proper pattern.
    {
        Console.WriteLine("B");
    }
}

public static class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        a.Dispose(); // Prints "A"

        B b = new B();
        b.Dispose(); // Prints "A"!
    }
}
从中可以看出,这使得使用dispose模式变得非常笨拙

您可以通过隐藏
public void Dispose(void)
然后在某个地方调用
base.Dispose()
来解决这个问题。然后,当调用
B=new B();B.Dispose();
时,它的工作方式与正确的Dispose模式“类似”,除非调用
ab=new B();B.Dispose();
,它只调用
A
Dispose
方法

public class B : A
{
    public void Dispose() // Causes CA error with or without "new".
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) // Proper pattern.
    {
        base.Dispose(); // Writes "A" (without quotes).
        Console.WriteLine("B");
    }
}
基本上,这整件事看起来很糟糕。我们知道CA是否接受
private void Dispose(bool)
这是一个bug,是否有办法至少向StyleCop发出警告

编辑:我不认为我应该接受Alexandre的答案,因为相对于我的问题,它基本上可以归结为“可能是一个bug”,以及一些应该是评论的东西。如果其他人有更具决定性的东西,我认为这将是一个更合适的答案。

IDisposable接口要求实现单个 无参数方法,Dispose.但是Dispose模式需要实现两种处理方法

  • 公共非虚拟(在Visual Basic中不可继承)IDisposable.Dispose实现,该实现没有参数
  • 受保护的虚拟(在Visual Basic中可重写)Dispose方法
由于该类型的使用者调用了非虚拟(在Visual Basic中不可继承)的public无参数Dispose方法,其目的是释放非托管资源,并指示终结器(如果存在)不必运行。因此,它有一个标准实现:

public void Dispose()
{
   // Dispose of unmanaged resources.
   Dispose (true);
   // Suppress finalization.
   GC.SuppressFinalize (this);
}
在第二个重载中,disposing参数是一个布尔值,指示方法调用是来自Dispose方法(其值为true)还是来自终结器(其值为false)

当垃圾回收器决定不再需要您的对象时,它将尝试完成它,以防您忘记调用无参数dispose方法,因为如果您这样做并且您遵循该模式,则调用将被抑制

见:

私有与受保护虚拟: 如果您想要支持正确遵循该模式的子类,那么应该始终使用受保护的虚拟对象,正如文档中所述

为什么有些人使用私有版本?可能是因为继承从来都不是他们的目的,特别是如果你只是在使用诸如Resharper之类的工具动态生成方法,那么这些方法大部分时间都是私有的

为什么代码分析不报告问题?
可能是一个bug。提供一个小样本来说明问题,以便其他人可以在他们的机器上进行测试。

密封类如何?对于开放类应使用Protected,对于密封类应使用private。这两种情况都适用。我们发现了几个未密封类没有引发问题的地方。尽管如此,这个私有类是密封类所必需的。不过,如果该类是未密封的,CA抛出该类会很好(而且它也应该知道这一点)。我认为我的编辑说明了为什么不抛出该类可能不是完全不可能的,但仍然有点烦人。调用
base.Dispose()
显然违反了该模式,因此我不认为它能解释这一点。我同意您最初的想法,即代码分析应该报告您提出的案例。我将使用全部。这篇文章中有很多问题。关键问题是:为什么建议的模式会发生更改,或者为什么代码分析不会发生更改投诉?当bool为真和假时,应该做什么不同的处理(bool)?在页()的末尾您将看到一个示例,如果为true,则必须处置所有资源,因为您调用了dispose方法并希望收回所有使用的内存。如果为false,则表示垃圾收集器正在删除该对象,那么您只需要处置非托管资源(在C#应用程序之外创建的对象),其余的对象可以保持不变,因为垃圾收集器将在需要时删除它们。