仅限受管资源的最小IDisposable implimenation

Ric*_*bob 11 c# dispose idisposable

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 TcpClient tpcClient;

    public override void Dispose() {
        (tcpClient as IDispose).Dispose();
        base.Dispose();
    }   
}
Run Code Online (Sandbox Code Playgroud)

refs:
MSDN
SO:我什么时候需要管理托管资源
SO:如何在C#中的Dispose()方法中部署托管资源
:SO:Dispose()用于清理托管资源

Joe*_*Joe 7

  1. 实现是正确的,没有问题,前提是没有派生类直接拥有非托管资源.

  2. 实施完整模式的一个很好的理由是"最少惊喜的原则".由于MSDN中没有描述这种简单模式的权威文档,维护开发人员可能会有疑虑 - 即使你觉得有必要问StackOverflow :)

  3. 是的,在这种情况下,Dispose可以是虚拟的.

  4. 如果调用了Dispose并且正确实现了(即调用GC.SuppressFinalize),则不必要的终结器的开销可以忽略不计

IDisposable.NET Framework之外的绝大多数类都是IDisposable因为它们拥有托管IDisposable资源.他们很少直接持有非托管资源 - 这只有在使用P/Invoke访问.NET Framework未公开的非托管资源时才会发生.

因此,推广这种简单模式可能是一个很好的理由:

  • 在极少数情况下使用非托管资源时,它们应该包装在一个密封的IDisposable包装类中,该类实现了终结器(如SafeHandle).因为它是密封的,所以这个类不需要完整的IDisposable模式.

  • 在所有其他情况下,绝大多数情况下,您可以使用更简单的模式.

但除非并且直到微软或其他权威消息来源积极推广它,否则我将继续使用完整IDisposable模式.