在.NET中重写Dispose(bool disposing)有什么意义?

时间:2009-02-25 02:55:18

标签: c# .net dispose idisposable

如果我用C#编写一个实现IDisposable的类,为什么我不能简单地实现

public void Dispose(){ ... } 

处理释放任何非托管资源?

protected virtual void Dispose(bool disposing){ ... }

总是必要的,有时是必要的,还是其他的东西?

8 个答案:

答案 0 :(得分:43)

包括终结器,引入新虚拟方法和“封装”原始处置方法的完整模式是非常通用的,涵盖所有基础。

除非您在非托管资源上有直接句柄(应该是almost never),否则您不需要终结器。

如果你密封了你的课程(我现在可能已经知道我对密封课程的看法 - design for inheritance or prohibit it),那么引入虚拟方法毫无意义。

我记不清上次以“复杂”的方式实施IDisposable而不是以最明显的方式实施,例如。

public void Dispose()
{
    somethingElse.Dispose();
}

有一点需要注意的是,如果您要使用非常强大的代码,那么应该确保您在处理后不会尝试做任何事情,并抛出{{ 1}}在适当的地方。这对于世界各地的开发人员都会使用的类库是一个很好的建议,但如果这只是一个在你自己的工作区中使用的类,那么很多工作只会获得很少的收益。

答案 1 :(得分:31)

这不是绝对必要的。它是推荐的Disposable模式的一部分。如果你还没有阅读关于这个的框架设计指南部分(第一版中的9.3,没有第二版方便对不起),那么你应该。 Try this link

它有助于区分一次性清理和可最终确定的垃圾收集 - 垃圾 - 我。

你不必那样做,但你应该阅读它并理解为什么这是推荐的,然后再将它作为不必要的折扣。

答案 2 :(得分:14)

MSFT文档中关于一次性模式存在一些偏见。您应该实现IDisposable有两个原因:

  1. 你有一个实现IDisposable的类型的字段
  2. 你有一个终结者。
  3. 案例1在大多数代码中都很常见。案例2在Microsoft编写的代码中很常见,它们是围绕非托管资源编写托管包装的代码,需要最终确定的代码。但是在你的代码中应该是非常罕见的。毕竟,你已经拥有了所有那些不错的.NET类来为你做脏工作。你只需要调用他们的Dispose()方法。

    仅案例2需要一次性图案。微软需要经常使用它。你大部分时间都只需要简单的Dispose()。

答案 3 :(得分:5)

除了其他好的答案之外,您可能还想查看这些文章:

答案 4 :(得分:3)

使用bool处理的附加方法来自某个框架设计指南。它只是一种模式,允许您的类可以多次调用dispose方法而不会抛出异常。这不是绝对必要的。从技术上讲,你可以在dispose方法中做到这一点。

答案 5 :(得分:1)

只是为了扩展其他人所说的内容:这不仅仅是因为你不需要'复杂的处理',而是你实际上不想要它 ,出于性能原因。

如果你去'复杂的配置'路线,并实现一个终结器,然后忘记显式处理你的对象,你的对象(以及它引用的任何东西)将在它真正处理之前经过额外的GC生成(因为它必须再挂一次让CLR调用终结器)。这只会导致您不需要更多的内存压力。此外,在整堆对象上调用终结器具有非常重要的成本。

请避免,除非您(或派生类型)拥有非托管资源。

哦,当我们在这个区域时:你的班级处理来自他人的事件的方法必须是“安全的”,面对你的班级被处置后被调用。最简单的方法是在处理类时执行无操作。见http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

答案 6 :(得分:1)

它给你的一件事是能够在与完成无关的Dispose()中工作,并且仍然清理非托管资源。

在终结器中对之外的托管对象执行任何非常......不可预测。大多数情况是由于你的终结器将在第二阶段以非确定性的方式关闭你的终结器 - 所以当你的终结器被调用时,你仍然有引用的对象很可能已经被最终确定。

将Dispose和finalizer调用分派给同一方法允许您共享关闭代码,而boolean参数允许您跳过托管清理(如果有)。

此外,该方法的虚拟化为继承者提供了一种简单的方法来添加自己的清理代码,而不会有无意中没有调用您的清理代码的风险。

答案 7 :(得分:1)

如果类实现IDisposable.Dispose()并且派生类需要添加其他逻辑,那么该类必须公开派生类可以链接到的某种Dispose方法。由于某些类可能在没有公共IDisposable.Dispose()方法的情况下实现Dispose(),因此在protected的所有实现中使用虚拟方法IDisposable非常有用他们是否有公共Dispose方法。在大多数情况下,bool参数并不是真正有意义的,但应该被认为是一个伪参数,使protected virtual Dispose(bool)具有与may-be-maybe-not不同的签名-public Dispose()

不使用protected virtual Dispose(bool)的类将要求派生类以不同于约定的方式处理其清理逻辑。某些语言(如C ++ / CLI)只能扩展遵循该约定的IDisposable实现,可能无法从非标准实现派生类。