终结器和 IDisposable
根据文档(MSDN:链接),很明显,在实现终结器时应该使用 IDisposable 模式。
但是,如果您实现 IDisposable(以便提供处理对象的确定性方法),并且没有任何非托管资源需要清理,您是否需要实现终结器?
在我看来,如果该类只有托管资源并且不调用 Dispose,托管资源将自动被 GC 清理,因此无需实现终结器。我错了吗?
另外,如果我使用 Dispose 方法来清理事件处理程序该怎么办?由于 GC 不会自动调用 Dispose,我是否应该实现 Finalizer,以确保事件处理程序未连线?
Based on the documentation (MSDN: link), it is clear that one should use the IDisposable pattern when implementing a finalizer.
But do you need to implement a finalizer if you implement IDisposable (so as to provide a deterministic way of disposing the object), and you dont have any unmanaged resources to clean up?
As I see it, if the class has only managed resources and if you dont call Dispose, the managed resources will automatically get cleaned up by the GC and hence no need to implement the finalizer. Am I wrong?
Also, what if I am using my Dispose method to clean up event handlers. As Dispose wont automatically get called by the GC, should I implement a Finalizer, to ensure that eventhandlers get unwired?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不,如果您有一个实现 IDisposable 的类(也就是说,如果您已正确实现该模式,并且您只有要处置的托管资源),则不需要实现终结器。
(如果这样做,它实际上会影响对象的生命周期,因为带有终结器的对象会被添加到 GC 中的终结队列中,并且可以比它们需要的时间更长 - 如果您的对象很大,这可能会成为问题.)
No, you do not need to implement a finalizer if you have a class that implements IDisposable (that is if you have implemented the pattern correctly, and that you only have managed resources to dispose of).
(If you do, it can actually affect the lifetime of your object, as objects with finalizers get added to the finalization queue in the GC and can live longer than they need to - this can be a problem if your objects are large.)
除非您有非托管资源,否则不应添加终结器。
拥有托管一次性资源但不拥有非托管资源的类应该实现完整的 Dispose 模式,但没有终结器。
如果该类没有
sealed
,则应在其Dispose()
方法中调用GC.SuppressFinalize(this)
,以防继承类添加终结器。You should not add a finalizer unless you have unmanaged resources.
A class that owns managed disposable resources but not unmanaged resources should implement the full
Dispose
pattern, but not have a finalizer.If the class is not
sealed
, it should callGC.SuppressFinalize(this)
in itsDispose()
method in case an inherited class adds a finalizer.不,你是对的,如果你的对象持有一个持有非托管资源的对象,那么你应该实现 IDisposable ,以便你可以在你的 Dispose 上调用它的 Dispose,但你不需要终结器,因为它的终结器将处理
通常,让一个类拥有 1 个或 0 个非托管资源会更好。如果它有 1 个非托管资源,则它应该具有处理它所需的尽可能少的其他状态(即没有其他一次性成员)。 SafeHandle 是处理这个问题的好方法。如果一个类需要处理多个非托管资源,则应该通过这些处理程序类处理所述资源来实现。然后是决赛& IDisposable 变得容易;要么你有唯一的非托管资源来处理这两个资源(如果调用了 dispose,则抑制终结器),或者你只需要 IDisposable。
因为直接处理非托管资源的情况相对较少,所以您可能永远不需要编写终结器(我想我在实际代码中已经这样做过一次)。因为明智的人不会在处理非托管资源的类中做太多其他事情,所以整个 Dispose(bool) 事情也是不必要的。
No, you are correct, if your object holds an object that holds an unmanaged resource then you should implement IDisposable so that you can call its Dispose on your Dispose, but you don't need a finaliser as its finaliser will deal with that matter.
Indeed, trying to do anything with a finalisable member from in a finaliser is fraught, as which order the finalisers will run is not deterministic, so you can get some nasty bugs if you try to do this.
As a rule it's much better to have a class either hold 1 or 0 unmanaged resources. And if it has 1 unmanaged resource, it should have as little other state as needed to deal with it (i.e. no other disposable members). SafeHandle is a good way of dealing with this. If a class needs to deal with several unmanaged resources it should do so by handling said resources through these handler classes. Then a finaliser & IDisposable becomes easy; either you have the sole unmanaged resource to deal with in both (suppress the finaliser if dispose is called) or you only need IDisposable.
Because having to deal with unmanaged resources directly is relatively rare, the chances are you will never have to write a finaliser (I think I have done so once, in real code). Because sensible people don't do much else in classes that handle unmanaged resources, the whole Dispose(bool) thing is unnecessary too.
是的,如果您只有托管资源,那么当发生垃圾收集时,它们将被 GC 清理(并且没有任何活动引用指向它们),
但在这种情况下,为什么需要在您的类型上实现 IDisposable 呢?我的意思是,你似乎认为在你的情况下,不处理你的物品并不是一个大问题,那么为什么有人会处理它们呢?
您还应该注意,使用终结器时垃圾收集会带来性能损失:任何具有终结器的对象都将逃脱第一个 GC 遍,如果这些对象寿命很短,这将大大降低 GC 效率。
在第一次垃圾收集期间,应该清理对象,但它不会,以便执行终结器。该对象将被 GC 视为长期存在,即使它应该已经被清理。
Yes, if you have only managed resources, they will be cleaned up by the GC when Garbage collection occurs (and there isn't any living references pointing to them)
But in this case, why do you need to implement IDisposable on your type? I mean, you seem to consider that in your case, not disposing your object is not a big issue, then why would someone dispose them?
You should also note that there is a performance penality with garbage collection while using Finalizers: Any object with a finalizer will escape the first GC pass, which will degrade GC efficiency quite a bit if these objects are short lived.
During the first garbage collection during which the object should be cleaned up, it won't, in order to execute the finalizer. The object will then be considered as long lived by the GC, even if it should already be cleaned.
如果您只有托管资源,那么您根本不需要实现 IDisposable。 IDisposable 旨在清理 GC 域之外的东西,例如本机句柄、数据库连接等。
如果您的控件包含实现 IDisposable 的控件,并且它们必须释放本机资源,那么您仍然需要实现 IDisposable 模式并给您的孩子控制一次处置机会。
在终结器中调用 Dispose() 的原因是作为最后的手段,如果对象没有正确处置,GC 会将其作为最后的努力。
If you only have managed resources, then you don't need to implement IDisposable at all. IDisposable is intended for cleaning up things beyond the GC's domain, such as native handles, database connections, etc.
If your control contains controls that implement IDisposable and they must release native resources, then you still need to implement the IDisposable pattern and give your child controls a chance to dispose.
The reason for calling Dispose() in the finalizer is as a last resort, if the object was not properly disposed, the GC will do it as a last ditch effort.
我从来没有需要实现终结器。如您所知,它使对象有机会在 GC 之前执行所需的操作。应在 dispose 方法中释放所有资源
I have never had the need to implement a finalizer. As you know, it gives the object a chance to do whatever it needs prior to GC. All resources should be freed up in the dispose method