由IDisposable 接口继承的对象都有Dispose()方法,他指释放由 Control 占用的非托管资源,还可以另外再释放托管资源。
一般情况下,凡是有Dispose()方法的对象都应该显式调用Dispose()方法来释放其占用的的资源。Close()指关闭一个Form。由于.net使用托管模式,因此其它的一般对象只要不在存在可用的引用,.net垃圾收集器会自动释放内存,必须要(也不可以)手动释放。
一般情况下,凡是有Dispose()方法的对象都应该显式调用Dispose()方法来释放其占用的的资源。Close()指关闭一个Form。由于.net使用托管模式,因此其它的一般对象只要不在存在可用的引用,.net垃圾收集器会自动释放内存,必须要(也不可以)手动释放。
析构函数用于销毁类的实例。析构函数是通过下面的形式声明的:[attributes] ~ identifier( ) { destructor-body }
此处: attributes(可选)
附加的声明性信息。有关属性和属性类的更多信息,请参阅 C# 属性。
identifier
identifier 与类名相同。
destructor-body
包含销毁类实例的语句的块。
备注
注意 不能对结构使用析构函数。只能对类使用析构函数。
一个类只能有一个析构函数。无法继承或重载析构函数。无法调用析构函数。它们是被自动调用的。 析构函数既没有修饰符,也没有参数。例如,下面是类 MyClass 的析构函数的声明:~ MyClass()
{
// Cleanup statements.
}
该析构函数隐式地对对象的基类调用 Object.Finalize 方法。这样,前面的析构函数代码被隐式地转换为:protected override void Finalize()
{
try
{
// Cleanup statements.
}
finally
{
base.Finalize();
}
}
这意味着对继承链中的所有实例递归地(从派生相近程度最大的到派生相近程度最小的)调用 Finalize 方法。程序员无法控制何时调用析构函数,因为这由垃圾回收器决定的。垃圾回收器检查是否存在应用程序不再使用的对象。它认为这些对象符合销毁条件并回收这些对象占用的内存。程序退出时也会调用析构函数。注意 可以通过调用 GC.Collect 方法强制进行垃圾回收,但大多数情况下应避免这样做,因为这样会导致出现性能问题。有关更多信息,请参阅强制垃圾回收。
示例
下面的示例创建三个类,这三个类构成了一个继承链。类 First 是基类,Second 是从 First 派生的,而 Third 是从 Second 派生的。这三个类都有析构函数。在 Main() 中,创建了派生相近程度最大的类的实例。程序运行时,注意这三个类的析构函数会自动被调用,并且是按照从派生相近程度最大的到派生相近程度最小的次序调用。// Destructors1.cs
using System;class First
{
~First()
{
Console.WriteLine("First's destructor is called");
}
}class Second: First
{
~Second()
{
Console.WriteLine("Second's destructor is called");
}
}class Third: Second
{
~Third()
{
Console.WriteLine("Third's destructor is called");
}
}public class MainClass
{
public static void Main()
{
Third myObject = new Third();
}
}
输出
Third's destructor is called
Second's destructor is called
First's destructor is called
使用析构函数释放资源
一般来说,您不必像使用 C++ 时那样关注内存管理。这是因为 .NET 框架垃圾回收器会隐式地管理对象的内存分配和释放。但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。当对象符合销毁条件时,垃圾回收器会运行对象的 Finalize 方法。资源的显式释放
如果您的应用程序在使用昂贵的外部资源,则还建议您提供一种在垃圾回收器释放对象前显式地释放资源的方式。可通过实现 Dispose 方法(来自 IDisposable 接口)来完成这一点,该方法为对象执行必要的清理。这样可大大提高应用程序的性能。即使有这种对资源的显式控制,析构函数也是一种保护措施,可用来在对 Dispose 方法的调用失败时清理资源。