假设我有这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
?
答案 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);