我不是很理解java和c#等语言为什么会有终结器。据我所知,他们:
- 不保证运行(在 java 中)
- 如果他们确实运行了,他们可能会在相关对象成为最终确定对象之后运行任意时间
- 并且(至少在 java 中),它们会导致惊人的巨大性能下降,甚至无法坚持上课。
那么为什么要添加它们呢?我问了一个 friend ,他咕哝着说“你想有一切可能的机会来清理数据库连接之类的东西”,但这让我觉得这是一种不好的做法。为什么你应该依赖具有上述属性的东西来做任何东西,甚至作为最后一道防线?尤其是当类似的东西被设计到任何 API 中时,该 API 将被 mock 不存在。
最佳答案
嗯,在某些情况下,它们非常有用。
在 .NET CLR 中,例如:
- are not guaranteed to run
如果程序没有被终止,终结器最终将始终运行。它只是不确定何时运行。
- if they do run, they may run an arbitrary amount of time after the object in question becomes a candidate for finalization
这是事实,但是,它们仍然运行。
在 .NET 中,这非常非常有用。在 .NET 中,将 native 的非 .NET 资源包装到 .NET 类中是很常见的。通过实现终结器,您可以保证正确清理 native 资源。否则,用户将被迫调用方法来执行清理,这会大大降低垃圾收集器的效率。
准确知道何时释放您的( native )资源并不总是那么容易 - 通过实现终结器,您可以保证它们将被正确清理,即使您的类以不太完美的方式使用也是如此。
- and (at least in java), they incur an amazingly huge performance hit to even stick on a class
同样,.NET CLR 的 GC 在这方面有优势。如果您实现了正确的接口(interface) (IDisposable
),并且如果开发人员正确地实现了它,您就可以避免昂贵的完成部分的发生。这样做的方法是用户定义的清理方法可以调用 GC.SuppressFinalize ,绕过终结器。
这为您提供了两全其美的方法 - 您可以实现终结器和 IDisposable。如果您的用户正确处理了您的对象,则终结器不会产生任何影响。如果他们不这样做,终结器(最终)会运行并清理您的非托管资源,但您会在运行时遇到(小的)性能损失。
关于c# - 为什么java和c#有终结器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1850742/