欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-05 08:27:13
      一,使用Finalizer析构器   1,使用了Finalizer析构器的对象如何被回收?   在类中定...

 

 

 

一,使用Finalizer析构器

 

1,使用了Finalizer析构器的对象如何被回收?

 

在类中定义了析构器的对象将会被移动到一个专门的队列中,这个队列将作为它的应用程序根,而使队列中的对象存活的更久一点,在对象上面调用完析构函数后,对象才会从队列中清理掉。

 

2,使用示例

 

 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(小杯子已被打碎~~~~么么哒~~~~~);       
        }
    
    }


感觉从语法上很像C++,嘿嘿~

 

 

3,使用析构器该注意哪些问题?

 

1,开发这无法确切的得知析构函数何时会被调用

2,析构函数会延长对象的存活时间

3,不要在析构函数中编写阻塞方法或耗时的方法,析构函数应该是迅速释放完资源并结束的

4,如果程序运行期间一直没有进行垃圾回收,那么程序退出时会执行一次垃圾回收,并调用析构函数


 

二,实现IDisposable接口

 

Finalizer的执行时间是不确定的,有时候,我们期望客户端对象使用完毕后立即释放资源,此时可以实现Idispose接口。

 

试用了下这个接口在dispose的时候都会发生啥,感觉还是雷同C++,写个栗子自己观察下析构的时候会发生啥吧。

 

使用示例:

 

 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(销毁了~~~~);
        }

    }




三,结合析构函数和Dispose()

 

析构函数的主要问题在于:它不是立即被调用,而是在以后某个不确定的时间,执行垃圾回收时被调用。Dispose()方法也有自己的问题,就是客户端不一定会调用它。因此,最好的方法就是将这两者结合起来:

如果客户端调用了Dispose()方法,那么就不要让CLR去执行析构函数;

如果客户端没有调用,此时再进行析构。

 

结合使用Demo:

 

  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();  //调用父类的方法释放父类的资源
            }
            
        }
    
    }