析构函数又称终结器,用于析构类的实例。

定义

  析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。

析构函数简介

以C++语言为例:[1]  析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。
 析构函数的使用

  • 不能在结构中定义析构函数。只能对类使用析构函数。

  • 一个类只能有一个析构函数。

  • 无法继承或重载析构函数。

  • 无法调用析构函数。它们是被自动调用的。

  • 析构函数既没有修饰符,也没有参数。

声明:

class Car
{
~ Car() // destructor
{
// cleanup statements...
}
}

  该析构函数隐式地对对象的基类调用 Finalize。这样,前面的析构函数代码被隐式地转换为:

protected override void Finalize()
{
try
{
// cleanup statements...
}
finally
{
base.Finalize();
}
}

  这意味着对继承链中的所有实例递归地调用 Finalize 方法(从派生程度最大的到派生程度最小的)。

注意

不应使用空析构函数。如果类包含析构函数,Finalize 队列中则会创建一个项。调用析构函数时,将调用垃圾回收器来处理该队列。如果析构函数为空,则只会导致不必要的性能丢失。

程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。垃圾回收器检查是否存在应用程序不再使用的对象。如果垃圾回收器认为某个对象符合析构,则调用析构函数(如果有)并回收用来存储此对象的内存。程序退出时也会调用析构函数。

可以通过调用 Collect 强制进行垃圾回收,但大多数情况下应避免这样做,因为这样会导致性能问题有关更多信息,请参见强制垃圾回收

使用析构函数释放资源

通常,与运行时不进行垃圾回收的编程语言相比,C# 无需太多的内存管理。这是因为 .NET Framework 垃圾回收器会隐式地管理对象的内存分配和释放。但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。当对象符合析构时,垃圾回收器将运行对象的 Finalize 方法。

资源的显式释放

如果您的应用程序在使用昂贵的外部资源,则还建议您提供一种在垃圾回收器释放对象前显式地释放资源的方式。可通过实现来自 IDisposable 接口的 Dispose 方法来完成这一点,该方法为对象执行必要的清理。这样可大大提高应用程序的性能。即使有这种对资源的显式控制,析构函数也是一种保护措施,可用来在对 Dispose 方法的调用失败时清理资源。

示例

下面的示例创建三个类,这三个类构成了一个继承链。类 First 是基类,Second 是从 First 派生的,而 Third 是从 Second 派生的。这三个类都有析构函数。在 Main() 中,创建了派生程度最大的类的实例。注意:程序运行时,这三个类的析构函数将自动被调用,并且是按照从派生程度最大的到派生程度最小的次序调用。

class First
{
~First()
{
System.Console.WriteLine("First's destructor is called");
}
} class Second: First
{
~Second()
{
System.Console.WriteLine("Second's destructor is called");
}
} class Third: Second
{
~Third()
{
System.Console.WriteLine("Third's destructor is called");
}
} class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}

析构函数(C#)的更多相关文章

  1. .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]

    构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...

  2. 【C#】析构函数

    MSDN paper 析构函数 析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数. 析构函数往往用来做“清理善后” 的工作( ...

  3. c++虚析构函数

    虚析构函数的作用主要是当通过基类指针删除派生类对象时,调用派生类的析构函数(如果没有将不会调用派生类析构函数) #include <iostream> using namespace st ...

  4. 转:Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  5. c++单例模式为什么不在析构函数中释放静态的单例对象(转)

    需要清楚一下几点:   1.单例中的 new 的对象需要delete释放.   2.delete释放对象的时候才会调用对象的析构函数.   3.如果在析构函数里调用delete,那么程序结束时,根本进 ...

  6. C++构造函数/析构函数 设置成private的原因

    C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...

  7. 关于GC和析构函数的一个趣题

    这个有趣的问题感谢装配脑袋友情提供. 请看如下代码: public class Dummy { public static Dummy Instance; ; ~Dummy() { Instance ...

  8. C++构造函数和析构函数

    构造函数简介 在上一个章节我们在创建好类的对象之后,首先对它的每一个成员属性赋值之后再对它们进行输出操作,如果不赋值就输出,这些值就会是垃圾值.而为了代码的简介,一次性为所有成员属性初始化,C++的类 ...

  9. virtual 修饰符与继承对析构函数的影响(C++)

    以前,知道了虚函数表的低效性之后,一直尽量避免使用之.所以,在最近的工程中,所有的析构函数都不是虚函数.今天趁着还书的机会到图书馆,还书之后在 TP 分类下闲逛,偶然读到一本游戏编程书,里面说建议将存 ...

  10. 谈一谈.net析构函数对垃圾回收的影响

    之前忘了说了 代码都是在Release模式下运行的,现在补充上. 这里说析构函数,其实并不准确,应该叫Finalize函数,Finalize函数形式上和c++的析构函数很像 ,都是(~ClassNam ...

随机推荐

  1. 用nodejs把目录下所有用px做单位的css文件转化为用rem做单位的css文件

    20171105 1211/星期日 公司为了更好适配手机端,以前用px做单位的css文件,全部需要转化为用rem做单位,目前是1rem=37.5px;开发新项目时,还是用习惯的px写样式代码,完成UI ...

  2. 关于[LeetCode]Factorial Trailing Zeroes O(logn)解法的理解

    题目描述: Given an integer n, return the number of trailing zeroes in n!. 题目大意: 给定一个整数n,返回n!(n的阶乘)结果中后缀0 ...

  3. Sun 与 Oracle 合并的未来

    引言 SUN 2008 初 10 亿美元收购 MySQL Oracle 2009 年 4 月 74 亿美元收购 SUN Sun 与 Oracle 合并的未来 1,如果云计算对企业来说变得越来越重要,那 ...

  4. 解决EditText跟ScrollView滑动冲突

    etContent.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, Motion ...

  5. Android 获取手机信息

    private void initData() { TelephonyManager mTm = (TelephonyManager) getActivity().getSystemService(C ...

  6. 快看Sample代码,速学Swift语言(1)-语法速览

    Swift是苹果推出的一个比较新的语言,它除了借鉴语言如C#.Java等内容外,好像还采用了很多JavaScript脚本里面的一些脚本语法,用起来感觉非常棒,作为一个使用C#多年的技术控,对这种比较超 ...

  7. java两种动态代理方式的理解

    要理解动态代理,不妨先来看看一个静态代理的例子. 一.静态代理 以一个电商项目的例子来说明问题,比如我定义了一个订单的接口IOrder,其中有一个方法时delivery,代码如下. package c ...

  8. Spring MVC如何测试Controller(使用springmvc mock测试)

    在springmvc中一般的测试用例都是测试service层,今天我来演示下如何使用springmvc mock直接测试controller层代码. 1.什么是mock测试? mock测试就是在测试过 ...

  9. IDEA+PHP+XDebug调试配置

    XDebug调试配置 临时需要调试服务器上的PHP web程序,因此安装xdebug,下面简单记录 安装xdebug 下载最新并解压 wget https://xdebug.org/files/xde ...

  10. 自学Zabbix3.9.3-模板Templates-嵌套Nesting

    自学Zabbix3.9.3-模板Templates-嵌套Nesting 嵌套是一个模板包含一个或多个其他模板的方法.可以在一个"嵌套"模板中将一些模板链接在一起.嵌套的好处在于,只 ...