析构函数、dispose 和 finalize 方法的区别
Posted
技术标签:
【中文标题】析构函数、dispose 和 finalize 方法的区别【英文标题】:Difference between destructor, dispose and finalize method 【发布时间】:2012-12-08 22:15:11 【问题描述】:我正在研究垃圾收集器在 c# 中的工作原理。我对Destructor
、Dispose
和Finalize
方法的使用感到困惑。
根据我的研究和理解,在我的类中有一个 Destructor 方法将告诉垃圾收集器以析构方法中提到的方式执行垃圾收集,而该方法不能在类的实例上显式调用。
Dispose
方法旨在让用户控制垃圾回收。 Finalize
方法释放类使用的资源,但不释放对象本身。
我不确定我是否理解正确。请澄清疑惑。欢迎任何进一步的链接或指南。
【问题讨论】:
【参考方案1】:析构函数隐式调用 Finalize 方法,它们在技术上是相同的。 Dispose 可用于实现 IDisposable 接口的对象。
您可能会看到:Destructors C# - MSDN
析构函数隐式调用了基类的 Finalize 对象。
来自同一链接的示例:
class Car
~Car() // destructor
// cleanup statements...
析构函数的代码被隐式翻译成如下代码:
protected override void Finalize()
try
// Cleanup statements...
finally
base.Finalize();
你对析构函数的理解是对的:
来自MSDN
程序员无法控制何时调用析构函数 因为这是由垃圾收集器决定的。垃圾 收集器检查不再被 应用。如果它认为一个对象有资格销毁,它 调用析构函数(如果有)并回收用于存储的内存 物体。程序退出时也会调用析构函数。它是 可以通过调用 Collect 来强制进行垃圾收集,但大多数 时间,这应该避免,因为它可能会创建性能 问题。
【讨论】:
如何通过调用Collect()
强制垃圾回收可能会产生性能问题?
@Destructor,GC 的标记阶段使用 DFS,它相对于应用程序中的对象总数具有线性时间和空间复杂性。所以,最好还是让 GC 来决定什么时候使用这么多资源,不要自己去利用。【参考方案2】:
在 C# 术语中,析构函数和终结器基本上是可互换的概念,应该用于在收集类型时释放 非托管 资源,例如外部句柄。您需要编写终结器非常很少见。
问题在于 GC 是非确定性的,因此Dispose()
方法(通过IDisposable
)可以支持确定性 清理。这与垃圾回收无关,并允许调用者尽快释放任何资源。它也适用于托管资源(除了非托管),例如,如果你有一个封装(比如)数据库连接的类型,你可能想要处理也释放连接的类型。
【讨论】:
所以我觉得Destructor方法应该只包含在其销毁之前必须执行的代码,Finalize方法将主要从超类继承。 @VictorMukherjee 再次,它们(析构函数和终结器)是可以互换的。Dispose()
将被称为 before 销毁,但它既不称为析构函数也不是终结器
嗨,Marc,认为 GC 主要是确定性的,只是规则不为人所知,是否正确?我不是专家,一直在学习,我想知道您的评论是否只是在终结者与处置的背景下泛泛而谈?还是它非常不确定(尽管这可能是另一天的另一个问题)?
@AlexKeySmith 我不得不说后者,因为它受时间、CPU 活动和外部因素(如外部内存)控制
谢谢 Marc,这很有用;啊,所以即使基本规则是确定性的,它也受到应用程序控制之外的许多因素的控制,它实际上是非确定性的。感谢您的洞察力!以上是关于析构函数、dispose 和 finalize 方法的区别的主要内容,如果未能解决你的问题,请参考以下文章