一,使用Finalizer析构器
1,使用了Finalizer析构器的对象如何被回收?
在类中定义了析构器的对象将会被移动到一个专门的队列中,这个队列将作为它的应用程序根,而使队列中的对象存活的更久一点,在对象上面调用完析构函数后,对象才会从队列中清理掉。
2,使用示例
<span style="font-family:Microsoft YaHei;"> class Program { static void Main(string[] args) { Cup cup = new Cup() { CupName="lhc的小杯子~~~~" }; } } public class Cup { public string CupName { get; set; } ~Cup() { //此处放置析构代码:对比C++的析构函数,感觉意思是一样的 //这里放置释放资源的代码 Console.WriteLine("小杯子已被打碎~~~~么么哒~~~~~"); } }</span>
感觉从语法上很像C++,嘿嘿~
3,使用析构器该注意哪些问题?
1,开发这无法确切的得知析构函数何时会被调用
2,析构函数会延长对象的存活时间
3,不要在析构函数中编写阻塞方法或耗时的方法,析构函数应该是迅速释放完资源并结束的
4,如果程序运行期间一直没有进行垃圾回收,那么程序退出时会执行一次垃圾回收,并调用析构函数
二,实现IDisposable接口
Finalizer的执行时间是不确定的,有时候,我们期望客户端对象使用完毕后立即释放资源,此时可以实现Idispose接口。
试用了下这个接口在dispose的时候都会发生啥,感觉还是雷同C++,写个栗子自己观察下析构的时候会发生啥吧。
使用示例:
<span style="font-family:Microsoft YaHei;"> static void Main(string[] args) { #region 构造器使用 //Cup cup = new Cup() { // CupName="lhc的小杯子~~~~" //}; #endregion #region dispose的使用 BigCup bigCup = new BigCup() { CupName = "lhc的小杯子" }; //try //{ // bigCup.CupName = "此处模拟对象的使用过程"; //} //finally //{ // IDisposable dis = bigCup as IDisposable; // if (dis != null) // { // dis.Dispose(); // } //} using (bigCup as IDisposable) { bigCup.CupName = "此处模拟对象的使用过程"; } #endregion } } public class BigCup : IDisposable { public string CupName { get; set; } void IDisposable.Dispose() { Console.WriteLine("销毁了~~~~"); } } </span>
三,结合析构函数和Dispose()
析构函数的主要问题在于:它不是立即被调用,而是在以后某个不确定的时间,执行垃圾回收时被调用。Dispose()方法也有自己的问题,就是客户端不一定会调用它。因此,最好的方法就是将这两者结合起来:
如果客户端调用了Dispose()方法,那么就不要让CLR去执行析构函数;
如果客户端没有调用,此时再进行析构。
结合使用Demo:
<span style="font-family:Microsoft YaHei;"> public class TestFatherFinalizerAndDispose :IDisposable{ private bool _dispose = false; ~TestFatherFinalizerAndDispose() { Console.WriteLine("调用析构函数~~~~"); } public void IDisposable.Dispose() { if (!_dispose) { _dispose = true; CleanUp(); GC.SuppressFinalize(this);//指示垃圾回收期,无视该对象的析构函数。 } } //子类可重写该释放资源方法 public virtual void CleanUp() { //此处放置清理资源代码 Console.WriteLine("垃圾清理完毕~"); } } public class TestSonFinalizerAndDispose : TestFatherFinalizerAndDispose { public override void CleanUp() { try { Console.WriteLine("此处填写释放子类型资源的方法"); } finally { base.CleanUp(); //调用父类的方法释放父类的资源 } } } </span>
完美解决~~~继续准备运筹学考试,话说复习好无聊的,中间写个代码解解闷儿~~