.net中对象占用资源的回收




    一,使用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>

     

       完美解决~~~继续准备运筹学考试,话说复习好无聊的,中间写个代码解解闷儿~~








                         

上一篇:吴恩达成立新公司,签约富士康,专注制造业AI变革(附视频)


下一篇:如何在 PhpStorm 使用 Code Generation?