被淡忘的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 分类下闲逛,偶然读到一本游戏编程书,里面说建议将存 ...
随机推荐
- (翻译)从底层了解ASP.NET体系结构 [转]
转自:http://www.cnblogs.com/rijing2004/archive/2007/09/14/howaspnetwork.html 前言 关于ASP.NET的底层的工作机制,最近园子 ...
- Windows Azure存储容器私有,公共容器,公共Blob的区别
当我们在Windows Azure中创建或编辑存储的容器时,需要选择访问类型,本文将描述一下这三个选项的区别. 1. 私有: 默认选项,顾名思义,用户不能通过URL匿名进行访问容器或容器内的任何Blo ...
- ubuntu cloud-archive 软件包 无法验证包来源
- 【转】大数据以及Hadoop相关概念介绍
原博文出自于: http://www.cnblogs.com/xdp-gacl/p/4230220.html 感谢! 一.大数据的基本概念 1.1.什么是大数据 大数据指的就是要处理的数据是TB级别以 ...
- NetBeans平台中调用状态栏
http://blog.csdn.net/mycsoft/article/details/2326386 StatusDisplayer stD = StatusDisplayer.getDefaul ...
- 完成端口(CompletionPort)详解
手把手叫你玩转网络编程系列之三 完成端口(Completion Port)详解 ...
- My集合框架第五弹 最小堆
二叉堆(以最小堆为例),其具有结构性质和堆序性质结构性质: 堆是一棵完全的二叉树,一颗高为h的完全二叉树有2^h到2^h-1个节点,高度为log N 而且该结构可以很容易的使用数 ...
- Kafka架构设计:分布式发布订阅消息系统
[http://www.oschina.net/translate/kafka-design](较长:很详细的讲解) [我们为什么要搭建该系统]用作LinkedIn的活动流(activity stre ...
- 国内外从事CV相关的企业[转]
提示:本文为笔者原创,转载请注明出处:blog.csdn.net/carson2005 经常碰到朋友问我国内从事计算机视觉(CV)领域的公司的发展情况,产品情况,甚至找工作等问题,这里,我给出自己收集 ...
- ORA-04091: 表 发生了变化, 触发器/函数不能读它
触发器中新调用了一个存储过程. 触发器: create or replace trigger tr_credits_wzclorder_clwzjk after update on app_wzclo ...