【原创】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分享
[解决办法]
学到不少东西。
楼主研究很深入啊,让我了解了一下垃圾回收机制。
[解决办法]
路过,帮顶
[解决办法]
学习
[解决办法]
学习
[解决办法]
好东西,顶起来。
[解决办法]
[解决办法]
支持原创,加精之
[解决办法]
[解决办法]
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(); 这里就应该调用才是了呀?
为什么楼主说被终结呢?
不太明白.
[解决办法]
学习了
[解决办法]
说得不错
[解决办法]
学习
[解决办法]
支持
[解决办法]
好帖,学习啦