被淡忘的c#析构函数
析构函数在C#中已经很少使用了,以至于很多人已经把它淡忘了,虽然用处不大,研究一下也无防。(原文:http://bbs.csdn.net/topics/300178463)
一. 析构函数的特征:
析构函数只能存在于类中,而不能存在于结构中;析构函数不能有任何修饰符,包括访问控制修饰符,静态修饰符,抽象修饰符,虚拟修饰符等都不能有;析构函数没有参数,这就意味着不能有任何重载。
二. 析构函数的调用时机:
析构函数会在对象被垃圾收集器回收时调用,但垃圾收集器有个特点,它是懒惰的, 它并不会在变量出了作用域和生命期后立即回收,而是在它认为适当的时候才回收,一般是内存紧张的时候。如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class MainForm : Form { Button btn = new Button(); public MainForm() { btn.Click += btn_Click; } void btn_Click( object sender, EventArgs e) { Demo de = new Demo(); } } class Demo { ~Demo() { MessageBox.Show( "析构函数被调用" ); } } |
在方法btn_Click返回后,de就应该被终结了,可是它的析构函数并没有被调用,说明垃圾收集器并没有将其回收;而当你关闭窗体的时候,析构函数被执行了,说明在程序结束的时候,垃圾收集器才不情愿地被迫将其回收(^-^)。 当然,我们可以调用GC.Collect()来强制回收:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class MainForm : Form { Button btn1 = new Button(); Button btn2 = new Button(); public MainForm() { btn1.Click += btn1_Click; btn2.Click += btn2_Click; btn2.Top = 40; this .Controls.Add(btn1); this .Controls.Add(btn2); } void btn1_Click( object sender, EventArgs e) { Demo de1 = new Demo(); de1 = null ; Demo de2 = new Demo(); new Demo(); GC.Collect(); } void btn2_Click( object sender, EventArgs e) { GC.Collect(); } } class Demo { ~Demo() { MessageBox.Show( "析构函数被调用" ); } } |
单击btn1的时候,de1和new Demo()被终结,析构函数被调用。 而de2尚未出生命期,所以虽然调用了GC.Collect方法,也不会回收;当btn1_Click返回时,de2出了生命期,但由于垃圾收集器的懒惰性,所以仍然没被回收;直到单击btn2调用GC.Collect方法,de2才被回收,其析构函数才被调用。
有一种办法能够阻止析构函数的调用,那就是实现IDisposable接口,这个接口定义了一个唯一的方法:Dispose()。 这样做之所以能阻止析构函数,是因为内部通常调用了GC.SuppressFinalize()方法,换句话说,如果你闲得无聊,完全可以实现这个接口,却不去调用GC.SuppressFinalize方法(^-^),这样的话就没任何意义了,因为阻止不了析构函数:
1
2
3
4
5
6
7
8
|
void btn1_Click( object sender, EventArgs e) { Demo de1 = new Demo(); Demo de2 = new Demo(); GC.SuppressFinalize(de1); de1 = null ; GC.Collect(); } |
现在de1的析构函数就不会被调用了。
三. 析构函数的本质:
析构函数本质上是一个方法,其形式如下:
1
2
3
|
protected void Finalize() { } |
通常我们认为析构函数只能由系统调用,而不能由程序员自己去调用,其实这不完全正确,析构函数也可以被显式调用,毕竟它也只是一个方法:
1
2
|
Demo de = new Demo(); typeof (Demo).GetMethod( "Finalize" ,BindingFlags.Instance|BindingFlags.NonPublic).Invoke(de, null ); |
被淡忘的c#析构函数的更多相关文章
- .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]
构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...
- 【C#】析构函数
MSDN paper 析构函数 析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数. 析构函数往往用来做“清理善后” 的工作( ...
- c++虚析构函数
虚析构函数的作用主要是当通过基类指针删除派生类对象时,调用派生类的析构函数(如果没有将不会调用派生类析构函数) #include <iostream> using namespace st ...
- 转:Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...
- c++单例模式为什么不在析构函数中释放静态的单例对象(转)
需要清楚一下几点: 1.单例中的 new 的对象需要delete释放. 2.delete释放对象的时候才会调用对象的析构函数. 3.如果在析构函数里调用delete,那么程序结束时,根本进 ...
- C++构造函数/析构函数 设置成private的原因
C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...
- 关于GC和析构函数的一个趣题
这个有趣的问题感谢装配脑袋友情提供. 请看如下代码: public class Dummy { public static Dummy Instance; ; ~Dummy() { Instance ...
- C++构造函数和析构函数
构造函数简介 在上一个章节我们在创建好类的对象之后,首先对它的每一个成员属性赋值之后再对它们进行输出操作,如果不赋值就输出,这些值就会是垃圾值.而为了代码的简介,一次性为所有成员属性初始化,C++的类 ...
- virtual 修饰符与继承对析构函数的影响(C++)
以前,知道了虚函数表的低效性之后,一直尽量避免使用之.所以,在最近的工程中,所有的析构函数都不是虚函数.今天趁着还书的机会到图书馆,还书之后在 TP 分类下闲逛,偶然读到一本游戏编程书,里面说建议将存 ...
随机推荐
- 设置UINavigationController相同标题
设置UINavigationController相同标题,让UINavigationController内的每一个ViewController的标题都一样,可以使用以下设置. UINavigation ...
- jquerymobile,手机端click无效
1.直接把<script>放到html代码后面,不要放到@section里面. 2.使用代理.如下所示: <script type="text/javascript&quo ...
- jq 弹出窗口
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- Cocos2d-x 关于Android.mk 自动读入CPP
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- (翻译)异步编程之Promise(1):初见魅力
原文:https://www.promisejs.org/ by Forbes Lindesay 异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2) ...
- webrtc--AudioProcessing的使用
1.AudioProcessing的实例化和配置: AudioProcessing* apm = AudioProcessing::Create(0); apm->level_estimator ...
- Win7系统下利用U盘安装Ubuntu14.04麒麟版
转自http://www.360doc.cn/article/14743053_335473181.html 重要提示:在采用u盘安装ubuntu分区时,所有磁盘一定要全部设置成逻辑分区,包括根目录/ ...
- DSp寄存器“是怎么和板子上的”具体地址“一一对应起来的
转自:http://hzcjustfly.blog.163.com/blog/static/18319712920117191123928/ 最近在学习DSP,今天在开发板TMS320F2808学习例 ...
- hdu 2899 Strange fuction
http://acm.hdu.edu.cn/showproblem.php?pid=2899 Strange fuction Time Limit: 2000/1000 MS (Java/Others ...
- Uncaught TypeError: Object #<Object> has no method 'fancybox'
Uncaught TypeError: Object #<Object> has no method 'fancybox' 2011-10-24 16:51:19| 分类: html|举 ...