如何处理IDisposable?

时间:2013-08-14 12:36:05

标签: c# .net idisposable

假设我有这3个班级。

abstract class MyBase
{
    //some base code here
}

class Foo : MyBase, IDisposable
{
    //got at least a field I should dispose
}

class Bar : MyBase, IDisposable
{
    //got at least a field I should dispose
}

我有几个这样的课程。我得到了拥有List<base>的课程。我怎样才能正确处理所有这些类而无需测试/强制转换以获得正确的类型然后使用Dispose

2 个答案:

答案 0 :(得分:8)

你可以使用:

foreach (var disposable in list.OfType<IDisposable>())
{
    disposable.Dispose(); 
}

我认为,通常 一个坏主意,但这种类层次结构是不可能的;这意味着客户不能以相同的方式使用“MyBase的任何实例”,因为特定类型还有其他合同。使Base实施IDisposable更加清晰,即使少数特定类型实际上并不需要它。

答案 1 :(得分:4)

如果可处置性是基类合同的一部分,为什么不明确说明呢?

abstract class MyBase : IDisposable
{
    //some base code here

    //an abstract "implementation" of the interface
    public abstract void Dispose();
}

这样,您可以确定其所有后代实际上都是一次性的。您还可以创建集合类而不是通用列表:

class MyBaseCollection : IEnumerable<MyBase>
{
    private List<MyBase> innerCollection;
    ....
    public void DisposeItems()
    {
       // call Dispose on each item here
    }
}

正确处理非托管资源可能非常棘手,并且对调试有抵抗力。在具体类上实现IDisposable接口时,您应该遵循Dispose pattern

在抽象类本身中,您可以根据要对类层次结构执行的操作执行多项操作。

  • 如果所有(或大多数)后代都需要处理逻辑,则可以强制它们使用以下方法实现Dispose模式的两种方法:

    public abstract void Dispose();
    public abstract void Dispose(bool disposing);
    

    这样,后代别无选择,只能实现方法,否则代码无法编译。

  • 如果大多数类不需要处理,但其中一些仍然需要处理,我会在基类中声明虚方法:

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

    对于大多数后代来说,这个默认实现已经足够了,那些需要处理的人可以随意覆盖它。

  • 此外,由于Dispose()方法的代码几乎总是相同的,您可以实现那个,并将另一个保留为虚拟甚至抽象。

    //should not be overridden
    public virtual void Dispose(){
      Dispose(true);
      GC.SuppressFinalize(this);
    }
    
    //must be overriden
    public abstract void Dispose(bool disposing);