如何处理IDisposable
本文关键字:IDisposable 处理 何处理 | 更新日期: 2023-09-27 18:27:50
假设我有这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
?
您可以使用:
foreach (var disposable in list.OfType<IDisposable>())
{
disposable.Dispose();
}
不过,我想说通常使用这种类层次结构是个坏主意;这意味着客户端不能以同样的方式只使用"MyBase
的任何实例",因为对于特定类型还有额外的约定。使Base
实现IDisposable
会更干净,即使少数特定类型实际上并不需要它。
如果可处置性是基类契约的一部分,为什么不明确说明呢?
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模式。
在抽象类本身中,您可以根据您想对类层次结构做什么来做一些事情。
如果所有(或大多数)子代都需要处理逻辑,您可以强制它们使用以下方法实现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);