【原创】C#深入剖析(2)——析构函数

CsToD 2009-04-07 09:11:33
加精
第二篇 析构函数

析构函数在C#中已经很少使用了,以至于很多人已经把它淡忘了,虽然用处不大,研究一下也无防。

一. 析构函数的特征:

析构函数只能存在于类中,而不能存在于结构中;析构函数不能有任何修饰符,包括访问控制修饰符,静态修饰符,抽象修饰符,虚拟修饰符等都不能有;析构函数没有参数,这就意味着不能有任何重载。

二. 析构函数的调用时机:

析构函数会在对象被垃圾收集器回收时调用,但垃圾收集器有个特点,它是懒惰的,
它并不会在变量出了作用域和生命期后立即回收,而是在它认为适当的时候才回收,一般是内存紧张的时候。如:

    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()来强制回收:

    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方法(^-^),这样的话就没任何意义了,因为阻止不了析构函数:


       void btn1_Click(object sender, EventArgs e)
{
Demo de1 = new Demo();
Demo de2 = new Demo();
GC.SuppressFinalize(de1);
de1 = null;
GC.Collect();
}

现在de1的析构函数就不会被调用了。

三. 析构函数的本质:

析构函数本质上是一个方法,其形式如下:

        protected void Finalize()
{
}

通常我们认为析构函数只能由系统调用,而不能由程序员自己去调用,其实这不完全正确,析构函数也可以被显式调用,毕竟它也只是一个方法:

Demo de = new Demo();
typeof(Demo).GetMethod("Finalize",BindingFlags.Instance|BindingFlags.NonPublic).Invoke(de, null);



...全文
1941 108 打赏 收藏 转发到动态 举报
写回复
用AI写文章
108 条回复
切换为时间正序
请发表友善的回复…
发表回复
专爆菜鸟 2010-08-06
  • 打赏
  • 举报
回复
支持,学习了
聖少俊 2009-05-05
  • 打赏
  • 举报
回复
学习
sombrebai 2009-04-09
  • 打赏
  • 举报
回复
好东西
ztmdsbt 2009-04-09
  • 打赏
  • 举报
回复
析构是不是就是构造函数?
如果是的话,
"在方法btn_Click返回后,de就应该被终结了,可是它的析构函数并没有被调用" Demo de = new Demo(); 这里就应该调用才是了呀?
为什么楼主说被终结呢?
不太明白.
FlappyBrid 2009-04-09
  • 打赏
  • 举报
回复
近来学习学习
huadust 2009-04-09
  • 打赏
  • 举报
回复
击btn1的时候,de1和new Demo()被终结

没有转过弯来。。。

qinggeer 2009-04-09
  • 打赏
  • 举报
回复
来学习,呵呵,不错,收藏一下。
RFEZGC 2009-04-09
  • 打赏
  • 举报
回复
了解了
原来也可以显式调用吸够函数的
ylwqhr 2009-04-09
  • 打赏
  • 举报
回复
学习, 谢谢分享
liucfy 2009-04-09
  • 打赏
  • 举报
回复
csucj 2009-04-09
  • 打赏
  • 举报
回复
Mark!
believeken 2009-04-09
  • 打赏
  • 举报
回复
学习 学习 高手和非高手的差距就在细节上啊~~~~~~
wangxianshou 2009-04-09
  • 打赏
  • 举报
回复
细微之处见真功夫啊
dddwwwxxxx 2009-04-09
  • 打赏
  • 举报
回复
好帖,学习啦
535cheng110 2009-04-09
  • 打赏
  • 举报
回复
支持
LemIST 2009-04-09
  • 打赏
  • 举报
回复
学习
飞天鹰 2009-04-09
  • 打赏
  • 举报
回复
学习了
xufzu123 2009-04-08
  • 打赏
  • 举报
回复
楼主能讲解一下什么时候要显式的定义析构函数吗?谢谢~~
lsd123 2009-04-08
  • 打赏
  • 举报
回复
.
qingtian878 2009-04-08
  • 打赏
  • 举报
回复
GOGO GOOD
加载更多回复(82)

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧