private void Dispose(bool)?

时间:2015-08-26 23:44:52

标签: c# code-analysis idisposable fxcop

在某些地方,人们建议使用private void Dispose(bool)作为IDisposable模式。这似乎已经过时了(至少对于未密封的类),因为新建议的模式(根据Microsoft)是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"!
    }
}

从这一点可以看出,它使得处理模式完全笨拙。

你可以通过隐藏public void Dispose(void)然后在某个地方调用base.Dispose()来解决这个问题。在调用B b = new B(); b.dispose();时调用A b = new B(); b.Dispose(); 除了之外,这与正确的处置模式“相似”,后者仅调用A的{​​{1}}方法

Dispose

基本上,整件事看起来很糟糕。我们是否知道它是否是CA接受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"); } } 的错误,是否有办法至少向StyleCop发出警告?

编辑:我认为我不应该接受亚历山大的回答,因为相对于我所拥有的问题,它基本上归结为“可能是一个错误”,以及应该作为评论的内容。如果其他人有更具决定性的东西,我认为这将是一个更合适的答案。

1 个答案:

答案 0 :(得分:6)

Implementing a Dispose Method

  

IDisposable 界面需要 单一的实施   无参数方法,Dispose。 然而配置模式需要 两个Dispose方法

     
      
  • 公共非虚拟(在Visual Basic中为NonInheritable)IDisposable.Dispose实现,没有参数。
  •   
  • 受保护的虚拟(在Visual Basic中可覆盖)Dispose方法。
  •   
     

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

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

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

当垃圾收集器决定不再需要你的对象时,如果你忘记调用无参数的dispose方法,它会尝试完成它,因为如果你这样做并且你正在遵循这个模式,那么调用将会被抑制

请参阅:How Finalization Works

私人与受保护虚拟:

如果你想要支持正确遵循模式的子类,你应该总是使用受保护的虚拟文件,如文档所示。

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

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

可能是个错误。提供一个小样本来解决问题,以便其他人可以在他们的机器上进行测试。