读书人

C#深入剖析(2)析构函数

发布时间: 2012-04-04 16:38:51 作者: rapoo

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

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

一.析构函数的特征:

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

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

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

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

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


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

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

三.析构函数的本质:

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

C# code
        protected void Finalize()        {        }

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

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





[解决办法]
up
[解决办法]
近来学习学习...
[解决办法]
没有研究过这方面的东西,学习了!
[解决办法]
技术文前排 呵呵

[解决办法]
好帖
[解决办法]
不错,经典的例子。


[解决办法]
UP学习
[解决办法]
mark
[解决办法]
学习啊,是得先把这些基础的问题搞明白!!
[解决办法]
up 学习
[解决办法]
学习了
[解决办法]
确实比较深入:)
[解决办法]
谢谢lz分享
[解决办法]
学到不少东西。
楼主研究很深入啊,让我了解了一下垃圾回收机制。
[解决办法]
路过,帮顶
[解决办法]
学习
[解决办法]
学习
[解决办法]
好东西,顶起来。
[解决办法]

引用楼主 CsToD 的帖子:
第二篇 析构函数

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

一. 析构函数的特征:

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

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

析构函数会在对象被垃圾收集器回收时调用,但…

[解决办法]
支持原创,加精之
[解决办法]
探讨
ojlovecd
麻烦把我的帖子中的C#深入剖析(1)——析构函数改成
C#深入剖析(2)——析构函数
这是第二篇文章了,发的时候写错了

[解决办法]
thx
[解决办法]
不错
[解决办法]
Mark!
[解决办法]
UP
[解决办法]
UP
[解决办法]
up
[解决办法]
谢了lz 哈哈哈
[解决办法]
ding
[解决办法]
支持lz,学习!期待后续..
[解决办法]
这里关于GC的部分似乎有些不够深入,容易造成一些误解:

以为GC.Collect()一旦调用,垃圾会被立即回收。


还是遵照微软建议较好,

1、没必要时不要写析构,而是实现IDispose接口。

2、不要在垃圾回收时处理任何有时间先后逻辑的事情,垃圾回收何时执行是不确定的。

[解决办法]
up
[解决办法]
UP!
[解决办法]
太深奥,我能学会吗????
[解决办法]
好贴,自己写的还是抄书的?

舞蝶飞数码创意

.net开发的图像处理软件。
图片合成flash
图片合成ppt
图片合成avi视频


免费照片边框

[解决办法]
mark
[解决办法]
期待下篇~
[解决办法]
先标记再学习
[解决办法]
很好啊,呵呵
[解决办法]
又是推荐帖,支持+学习
[解决办法]
学习,支持一下
[解决办法]
不错,挺透彻
[解决办法]
up
[解决办法]
mark@@@@
[解决办法]
好东西,学习ing……
[解决办法]
好帖,支持
[解决办法]
支持 帮顶~!!!
[解决办法]
学习中!
[解决办法]
收藏~
[解决办法]
学习了,感谢
[解决办法]
mark
[解决办法]
丿
[解决办法]
先顶 在学习
[解决办法]
楼主能讲解一下什么时候要显式的定义析构函数吗?谢谢~~
[解决办法]
学习
[解决办法]
学习!期待后续
[解决办法]
学习下
[解决办法]

[解决办法]
mark
[解决办法]
xuexi xue xi zaixuexi
[解决办法]
mark
[解决办法]
学习了
[解决办法]
mark
[解决办法]
学习
[解决办法]
赶紧学习一下
[解决办法]
赶紧学习一下
[解决办法]
xue习了
[解决办法]
楼的说得好,对于你个人来说,这样的收获会获益一辈子,
正所谓失败是成功之母,失败只不过是你成功的奠基石,LZ单枪匹马的干已经
很令人钦佩了
[解决办法]
mark下
------解决方案--------------------


GOGO GOOD
[解决办法]
GOGO GOOD
[解决办法]
.
[解决办法]
学习+up+接分
[解决办法]
不错!
[解决办法]
不错!
[解决办法]
析构函数一般不倡导使用,vs有垃圾回收机制可以自动释放内存。如果使用了析构函数,编译器就会把此放入统一资源回收中,以便内存需要时在释放。也就是说调用了析构函数后并不一定回立即释放内存。关于内存管理方面ms做的还可以的。
[解决办法]
up
[解决办法]
up
[解决办法]
感谢分享
[解决办法]
mark
[解决办法]
UP
[解决办法]
收藏 了
[解决办法]
此致,敬礼...........
[解决办法]
学习, 谢谢分享
[解决办法]
关于构造函数和析构函数,我喜欢用修房子和拆房子的比喻
[解决办法]
好东西
[解决办法]

[解决办法]
学习, 谢谢分享
[解决办法]
来学习,呵呵,不错,收藏一下。
[解决办法]
击btn1的时候,de1和new Demo()被终结

没有转过弯来。。。


[解决办法]
析构是不是就是构造函数?
如果是的话,
"在方法btn_Click返回后,de就应该被终结了,可是它的析构函数并没有被调用" Demo de = new Demo(); 这里就应该调用才是了呀?
为什么楼主说被终结呢?
不太明白.
[解决办法]
学习了
[解决办法]
说得不错
[解决办法]
学习
[解决办法]
支持
[解决办法]
好帖,学习啦

读书人网 >C#

热点推荐