IDisposable关于处理非托管资源的"标准完整" 实现有很多信息- 但实际上这种情况非常罕见(大多数资源已经被托管类包装).这个问题集中在更常见的"仅限托管资源"案例的IDisposable的最小实现上.
1:IDisposable下面的代码中的mimimal实现是否正确,是否存在问题?
2:是否有任何理由增加一个完整的标准IDisposable执行(Dispose(),Dispose(bool),Finalizer等)在最小的执行力度呈现的?
3:在这个极小的情况下,制作Dispose虚拟(因为我们没有提供Dispose(bool))是否可行/明智?
4:如果这个最小的实现被一个包含(在这种情况下是无用的)终结器的完整标准实现替换 - 这会改变GC处理对象的方式吗?有什么缺点吗?
5:示例包括Timer与事件处理程序,因为这些情况下,尤其重要的是不能错过的无法处理它们会保持对象活蹦乱跳(this在的情况下Timer,eventSource在事件处理程序的情况下),直到GC得到轮在释放他们是时候了.还有其他这样的例子吗?
class A : IDisposable {
private Timer timer;
public A(MyEventSource eventSource) {
eventSource += Handler
}
private void Handler(object source, EventArgs args) { ... }
public virtual void Dispose() {
timer.Dispose();
if (eventSource != null)
eventSource -= Handler;
}
}
class B : A, IDisposable {
private …Run Code Online (Sandbox Code Playgroud) IDisisposable模式实现起来很昂贵.在开始实际处理资源之前,我已经计算了17行代码.
Eric Lippert最近撰写了一篇博客文章,提出了一个有趣的观点:任何时候终结者都会运行,这是一个错误.我觉得这很有道理.如果始终遵循IDisposable模式,则应始终抑制Finalizer.它永远不会有机会跑.如果我们接受终结器运行是一个错误,那么有一个指导方针迫使开发人员从以下抽象类派生并禁止直接实现IDisposable接口.
public abstract class AbstractDisaposableBase: IDisposable
{
~AbstractDisaposableBase()
{
ReportObjectLeak();
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
[Conditional("DEBUG")]
private void ReportObjectLeak()
{
//Debug.Assert(false, "leaked instance");
//throw new Exception("leaked instance");
}
}
Run Code Online (Sandbox Code Playgroud)
好处很明显:
class MyClass1 : DisablableBase
{
protected override void Dispose(bool disposing)
{
//dispose both managed and unmamaged resources as though disposing==true
}
}
Run Code Online (Sandbox Code Playgroud)
没有处置对象报告
始终遵循一次性模式
但是,这样的指南有什么问题吗?
一个可能的问题是所有一次性物体都将定义一个终结器.但由于终结器总是受到抑制,因此不应该有任何性能损失.
你的想法是什么?