我们知道在代码里自己写 Dispose 来释放一些资源。但是你真的用对了吗 ? 本篇介绍一些不容易注意到的 GC 相关知识 。
当前类中出现 IO 操作。或者其他 跨语言调用,窗口和网络连接 之的非托管资源调用,这时才需要自己是实现一个IDispose 接口。其他的时候你并不需要去实现这样一个接口。我的做法是一般的类继承一个 IReset 接口,这个接口内只包含一个 Reset 函数 . Dispose 接口是一个显示的调用,如果我们没有写这个接口,运行时他会在执行析构函数的时候清理资源。
在使用Dispose 接口的同时 你或许同时会用到一个终结器。打个比方 如果你忘记显示调用 Dispose 函数的时候,程序还是会帮你清除非托管资源。
先观察以下析构函数
class Car
{
~Car() // finalizer
{
// cleanup statements...
}
}
上面的代码很简单,他等价于下面的代码
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
现在你应该已经观察到这一行代码被隐式调用了,这行代码的意义是将当前运行时 Finalize 队列中创建一个条目,等待回收器来处理该队列。
base.Finalize();
我们再观察下面的代码
public class MyClass
{
// 这里实现了IDispose中的 Dispose方法
public void Dispose()
{
//执行资源释放 xxxxxxxx
//告诉GC此对象的Finalize方法不再需要调用
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose();
}
}
//下面我们使用using使用这个类
using(MyClass s = new MyClass()){}
上面我们使用了 GC.SuppressFinalize(this);
函数,他会告诉GC的Finalize队列中移除当前,不必在执行 Finalize()
在 C# 语言里对析构函数与终结器的描述似乎是同一个东西,这让我有一点困惑。我查询了一些论文他们是这样说的。如果你感兴趣也可以看一下
In the C# world the terms “destructor” and “finalizer” seem to be used pretty much interchangeably, which I suspect is because the C# specification describes the non-deterministic cleanup functionality using the word “destructor”, whereas the CLR documentation always uses the word “finalizer”, so within the realms of C# they mean the same thing.
However, in the C++/CLI specification there is a distinction made between the two. It allows both deterministic and non-deterministic cleanup, and uses the term “destructor” for the deterministic functionality and “finalizer” for the non-deterministic functionality:
在C#世界术语“析构函数”和“终结”似乎要使用pretty多互换,我怀疑是因为C#规范用字“析构函数”,描述了非确定性的清理功能,而CLR的文档始终使用单词“终结”,所以C#的领域内,他们的意思是一样的。
然而,在C / CLI规范有两者之间作出区分。它同时允许确定性和非确定性的清理,并使用该确定的功能的非确定性的功能的术语“析构”和“终结”:
Microsoft 编程指南
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/destructors
析构函数和终结器的区别?(The difference between a destructor and a finalizer?
http://www.it1352.com/382928.html