为什么要实现IDisposable来清理非托管资源?

时间:2018-02-19 16:12:03

标签: c# .net

documentation

  

只有当您的类型直接使用非托管资源时,才应实现IDisposable。

来自大多数Java背景,这对我来说听起来很奇怪。假设我有一个包含IDisposable成员的类:

class Foo : IDisposable {
    private StreamWriter sw;
    ...
}

...并假设此类被用作一种过滤器,它接受字符串并修改它们,然后使用StreamWriter sw输出它们。我想把这个类用作一种Writer。

为什么我不想实现Dispose(bool)来调用sr.Dispose()?如果我用Java(Closable接口编写代码,我将不得不这样做类似于.NET的IDisposable,虽然在某些方面有所不同)。然而,文档说我不应该,因为我没有直接使用非托管资源。

如果我不覆盖Dispose(bool),那么当我离开sw语句启动的块时,托管资源using如何处置?

2 个答案:

答案 0 :(得分:3)

当您的班级包含IDisposable字段时,您应该实施IDisposable,例如StreamWriter

在这种情况下,您可以假设您的类型确实使用了非托管资源(通过StreamWriter类),并且您应该始终处置任何实现IDisposable接口的对象使用它们完成。

  

为什么我不想实现IDisposable(bool)来调用sr.Dispose()

你当然会。

  

如果我不覆盖Dispose(bool),那么当我离开sw语句启动的块时,托管资源using如何处置?

它没有。底层的非托管资源最终可能由终结器释放(取决于IDisposable类的实现),但是除非您在类中明确地处理它,否则托管对象不会被处置。

答案 1 :(得分:2)

当您使用实现IDisposable接口的实例时,最佳做法是将其用作using语句中的局部变量。
但是,这并不总是可行的 在某些情况下,您必须包含一个实现IDisposable接口的字段。在这些情况下,您还应该自己实现它并将它们放在类Dispose(bool)方法中。

例如,假设您要安排任务。一个相当容易的实现是使用包含System.Timers.Timer字段,开始,停止和doWork方法的类。 在这种情况下,您不能将计时器用作局部变量,它必须是一个字段,因此您的类应该实现IDisposable接口并在其上配置计时器{{1方法。

这是一个简化的代码示例(我想这有点过于简化,但对于此演示而言已经足够了)

Dispose(bool)