在.NET中重写Dispose(bool disposing)有什么意义?
如果我用C#编写一个实现IDisposable的类,为什么仅仅实现就不够用
public void Dispose(){ ... }
处理任何非托pipe资源?
是
protected virtual void Dispose(bool disposing){ ... }
总是必要的,有时是必要的,或者其他什么东西?
这不是绝对必要的。 它是推荐的一次性模式的一部分。 如果你还没有阅读这个框架devise指南部分(第一版9.3,没有第二版方便对不起),那么你应该。 试试这个链接 。
区分一次性清理和可终止的垃圾回收是我非常有用的。
你不必这样做,但你应该阅读它,并理解为什么这是build议之前,打折扣是不必要的。
包括终结者,引入新的虚拟方法和原始处置方法的“密封”在内的完整模式是非常普遍的,涵盖了所有的基础。
除非你有非托pipe资源上的直接句柄(这几乎 从不 ),你不需要一个终结器。
如果你把class级封闭起来(我现在可能已经知道封闭class级的意见了 – 为inheritancedevise或禁止它 ),引入一个虚拟方法是没有意义的。
我不记得我最后一次以“复杂”的方式实现IDisposable
,而最明显的方式是这样做
public void Dispose() { somethingElse.Dispose(); }
有一点需要注意的是,如果你需要真正健壮的代码,你应该确保在你处理ObjectDisposedException
之后不要做任何事情,并且在适当的时候抛出ObjectDisposedException
。 对于世界各地的开发人员将使用的类库,这是一个很好的build议,但是如果这只是您自己的工作空间中使用的类,那么获得很less的收获就是很多的工作。
有关一次性模式的MSFT文档有一点偏见。 您应该执行IDisposable有两个原因:
- 你有一个实现IDisposable的types的字段
- 你有一个终结者。
情况1在大多数代码中很常见。 情况2在微软写的代码中很常见,他们是在非托pipe资源周围编写托pipe包装的那些,需要敲定的。 但是在你的代码中应该是非常罕见的。 毕竟,你已经有了所有这些漂亮的.NET类来为你做肮脏的工作。 你只需要调用他们的Dispose()方法。
只有情况2需要一次性模式。 微软需要使用它很多。 大部分时间你只需要简单的Dispose()。
除了其他的很好的答案,你可能想要检查这些文章:
- 正确实现IDisposable和Dispose模式
- IDisposable:你的母亲从来没有告诉你关于资源释放 (一次性devise原则)
bool处理的附加方法出自某个框架devise指南。 这只是一个模式,让你的类可以多次调用dispose方法而不会抛出exception。 这不是绝对需要的。 从技术上讲,你可以在处理方法中做到这一点。
只是为了扩展别人的话:不仅仅是因为性能的原因,你不需要 “复杂的configuration”,而是你实际上不需要它 。
如果你走“复杂的configuration”路线,并实现一个终结器,然后忘记明确地处理你的对象,你的对象(和它引用的任何东西)将存活一个额外的GC世代之前真正处置(因为它必须挂在一更多的时间让CLR打电话给终结者)。 这只会导致更多的内存压力,你不需要。 另外,在整个堆对象上调用终结器也有不小的成本。
所以避免,除非你(或你的派生types)有非托pipe资源。
哦,当我们进入这个区域的时候:在你的课程被处理之后,在你的课堂上处理事件的方法必须是“安全的”。 最简单的是如果这个类被丢弃,那么就执行一个no-op。 请参阅http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
它提供的一件事就是能够在Dispose()中与Finalization无关地工作,并且仍然清理非托pipe资源。
在终结器中对“自己”以外的被pipe理对象做任何事情都是非常难以预料的。 这大部分是因为你的终结器将在第二阶段以非确定的方式closures你的AppDomain – 所以当你的终结器被调用的时候,很有可能你仍然有引用的对象已经被最终确定。
将Dispose和finalizer调用分派到相同的方法允许您共享您的closures代码,而布尔参数允许您跳过托pipe清理(如果有)。
而且,方法的虚拟性为inheritance者提供了一个简单的方法来添加他们自己的清理代码,而不必担心无意中调用你的代码。
如果一个类实现了IDisposable.Dispose()
并且派生类需要添加额外的逻辑,那么这个类必须公开派生类可以链接的某种Dispose
方法。 由于某些类可能实现了IDisposable.Dispose()
而没有公共的Dispose()
方法,因此在IDisposable
所有实现中都有一个虚拟方法是有用的,无论它们是否具有公共的Dispose
方法。 在大多数情况下, bool
参数并不是真正有意义,但应该被认为是一个虚拟参数,以使被protected virtual Dispose(bool)
具有与may-be-or-maybe-not-public Dispose()
。
不使用protected virtual Dispose(bool)
类将需要派生类以不同于约定的方式处理其清理逻辑。 一些像C ++ / CLI这样的语言只能用来扩展遵循这个约定的IDisposable
实现,可能无法从非标准实现中派生类。