析构函数用于析构类的实例。
-
不能在结构中定义析构函数。只能对类使用析构函数。
-
一个类只能有一个析构函数。
-
无法继承或重载析构函数。
-
无法调用析构函数。它们是被自动调用的。
-
析构函数既没有修饰符,也没有参数。
例如,下面是类 Car 的析构函数的声明:
class Car
{
public int CarID { get; set; }
~Car()
{
//在析构函数中,可以执行释放其他托管资源处理
Console.WriteLine($"当前Car对象被释放,CarID={CarID}");
}
}
该析构函数隐式地对对象的基类调用 Finalize。这样,前面的析构函数代码被隐式地转换为:
protected override void Finalize()
{
try
{
// cleanup statements...
}
finally
{
base.Finalize();
}
}
这意味着对继承链中的所有实例递归地调用 Finalize 方法(从派生程度最大的到派生程度最小的)。
注意 |
---|
不应使用空析构函数。如果类包含析构函数,Finalize 队列中则会创建一个项。调用析构函数时,将调用垃圾回收器来处理该队列。如果析构函数为空,则只会导致不必要的性能丢失。 |
程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。垃圾回收器检查是否存在应用程序不再使用的对象。如果垃圾回收器认为某个对象符合析构,则调用析构函数(如果有)并回收用来存储此对象的内存。程序退出时也会调用析构函数。
可以通过调用 Collect 强制进行垃圾回收,但大多数情况下应避免这样做,因为这样会导致性能问题。有关更多信息,请参见强制垃圾回收。
如果您的应用程序在使用昂贵的外部资源,则还建议您提供一种在垃圾回收器释放对象前显式地释放资源的方式。可通过实现来自 IDisposable 接口的 Dispose 方法来完成这一点,该方法为对象执行必要的清理。这样可大大提高应用程序的性能。即使有这种对资源的显式控制,析构函数也是一种保护措施,可用来在对 Dispose 方法的调用失败时清理资源。
测试代码:
static void TestOne()
{
Car car1 = new Car() { CarID = 1 };
//将car1引用设置为空
car1 = null;
//手动调用GC垃圾回收
Console.WriteLine("手动触发垃圾回收>");
GC.Collect(); //释放内存操作,是异步执行的
Console.WriteLine(car1 == null);
}
特别说明:
1.静态类GC中提供了强制回收的接口
2.回收操作是异步执行的。
更多:
内容来自: