根据如何使用 IDisposable 的模式,微软建议使用 finalize 来释放非托管源。 http://msdn.microsoft.com/en-us/library/system.idisposable%28v=VS.80%29.aspx
但是,如果我们在 finalize 中编写一些代码来发布托管源代码会发生什么?也就是说当 GC 调用 finalize 释放一些托管源时,会发生什么?
根据如何使用 IDisposable 的模式,微软建议使用 finalize 来释放非托管源。 http://msdn.microsoft.com/en-us/library/system.idisposable%28v=VS.80%29.aspx
但是,如果我们在 finalize 中编写一些代码来发布托管源代码会发生什么?也就是说当 GC 调用 finalize 释放一些托管源时,会发生什么?
It's a bad practice in general. In finalizer code you can't rely on state of you object and its managed resources - they can be collected or disposed/finalized already. Also, you can't rely on order, in which CLR calls Finalize
.
通常,Finalize
用于清理外部托管资源是无用的,并且可能很危险。当对象终结器运行时,它拥有的托管资源可能是:
在某些情况下,让终结器调用其他托管对象上的清理代码可能会有所帮助,但这种调用通常只适用于对象知道彼此内部细节的情况,并且通常应该使用protected
或internal
方法执行,或者使用私人交换的代表。例如,在某些情况下,可能有两个或多个对象相互了解,并且具有必须以特定顺序运行的终结器。
例如,可能有一个类的目的是向 USB 设备发送数据,而另一个类的目的是控制连接到该设备的设备。如果后一个类想要确保设备接收到“关闭”命令,则可能需要其终结器在 USB 连接类终结器关闭连接之前发送命令。处理此问题的最简洁方法可能是让 USB 连接对象的构造函数接受将从其终结器调用的回调。如果这个类没有这样的特性,事情可能会很糟糕。另一种方法可能是让一个与包装器分开的对象,它包含清理所需的所有信息,以及一个WeakReference
包装器对象,并有一个计时器滴答事件,如果WeakReference
死了。如果计时器绑定到创建包装器对象的线程,那么即使包装器对象被放弃,也可能允许执行清理,前提是线程仍然处于活动状态(如果可能不存在,事情会变得更加复杂)。
为什么(或者更好的是,如何)发布在终结器中管理的东西?当前对象拥有的所有东西此时都已被视为垃圾,并将在垃圾收集器的下一次运行中被收集。并且当前不拥有的所有东西都不能被释放,因为其他东西可能仍然引用它。
无需为托管代码编写 Dispose/Finalize。bcz 当不再引用该对象时,它将被 CLR 删除。Dispose 方法是为文件处理程序或数据库命令等非托管代码编写的。