private void Dispose(bool)?

本文关键字:bool void Dispose private | 更新日期: 2023-09-27 18:10:03

在一些地方,人们建议将private void Dispose(bool)用于IDisposable模式。这似乎过时了(至少对于未密封的类),因为新的建议模式(根据微软)是protected virtual void Dispose(bool)

问题是,代码分析没有报告private void Dispose(bool)违反CA1063,即使它似乎直接违反了模式。

这是怎么回事?private void Dispose(bool)是否以某种方式被调用(或编译为看起来像protected virtual Dispose(bool)的东西)?

如果这是代码分析的一些问题,并且是不正确的模式,是否有方法来检测它?可能用StyleCop?

编辑:经过考虑,是不是一个基类可以调用base.Dispose(),这将击中private 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 b = new B(); b.dispose(); 时,这与正确的处置模式"类似",除了调用A b = new B(); b.Dispose();,它只调用ADispose方法。

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");
    }
}
总的来说,这整件事看起来很糟糕。我们是否知道这是一个bug, CA接受private void Dispose(bool),是否有一种方法,至少抛出一个警告与StyleCop?编辑:我不认为我应该接受Alexandre的回答,因为相对于我的问题,它基本上可以归结为"可能是一个bug",以及一些应该是评论的东西。如果有人有更确凿的答案,我认为这将是一个更合适的答案。

private void Dispose(bool)?

实现Dispose方法

IDisposable接口要求实现一个单节点无参数方法, Dispose。然而dispose模式需要实现两个dispose方法:
    public non-virtual(在Visual Basic中是不可继承的)IDisposable。处理没有参数的实现。
  • 一个受保护的虚拟(在Visual Basic中可重写)Dispose方法。

因为public,非虚拟的(在Visual Basic中是不可继承的),无参数的Dispose方法是由该类型的使用者调用的,它的目的是释放非托管资源,并指出终结器(如果存在的话)不必运行。因此,它有一个标准实现:

public void Dispose()
{
   // Dispose of unmanaged resources.
   Dispose (true);
   // Suppress finalization.
   GC.SuppressFinalize (this);
}

在第二个重载中,Dispose形参是一个布尔值,指示方法调用是来自Dispose方法(其值为true)还是来自终结器(其值为false)

当垃圾收集器决定不再需要你的对象时,它将尝试结束它,以防你忘记调用无参数的dispose方法,因为如果你这样做了,并且你遵循这个模式,调用将被抑制。

参见:如何完成

私有vs受保护虚拟:

如果你想支持正确遵循模式的子类,你应该像文档所说的那样使用protected virtual。

为什么有些人使用私有版本?可能因为继承从来都不是他们的本意,特别是如果你只是使用Resharper之类的工具动态地生成方法,大多数时候这些方法都是私有的。

为什么代码分析不报告问题?

可能是一个bug。提供一个给出问题的小示例,以便其他人可以在他们的机器上进行测试。