c sharp圣经 version 5读书笔记 第8章 对象的生命周期

1. 概述:CLR通过垃圾回收来管理已分配的创建在托管堆中的实例。(什么时候回收?回收过程)。也可以通过System.GC类类型自己回收,接着分析怎样用System.Object.Finalize()虚方法和Idisposable接口建立即时释放内部非托管资源的类型。NET4新功能:后台垃圾回收和使用System.Lazy<>泛型类实现的延迟实例化。通过本章,你将会牢固地掌握CLR是怎样管理NET对象的。其实就是自定义变量生存周期而已,但是术语专业,吸引人来学习。

2. 类,对象和引用:new分配对象并返回引用

  Car refToMyCar=new Car();//refToMyCar是栈中变量,指向对中的Car内存块。结构是值类型。

       何时销毁new的内存块?当一个对象从代码库的任何部分都不可访问时,被销毁。类似于智能指针,但是没得AddRef()等方法而已。

       托管堆是一片连续的内存空间,新建的对象会被连续非配,在托管堆上,当堆中内存不足分配时,进行垃圾回收。但垃圾回收具体如何发生,取决于NET平台的版本。(这个和操作系统的内存分配?)

3. 应用程序根的作用:一个托管位置,其中保存着对托管堆上一个对象的引用。

       什么时候不需要一个对象?在一次垃圾回收过程中,通过建立对象图(对象A依赖与B等)来检查这些对象是否有活动根,删除垃圾对象,并重新整理内存。

       准确地说:垃圾回收器使用两个不同的堆,一个用来专门存储非常大的对象,这个堆在回收周期中较少顾及。

4. CLR试图寻找不可访问的对象时,它不会逐个检查托管堆上的每一个对象。

对象的代:对象在堆上存在的时间越长,它就更可能应该保留,

第0代:从没有被标记为回收的新分配的对象;

第1代:在上一次垃圾回收中没有被回收的对象(被标记为已回收,但因为已经获取了足够的堆空间而没有被删除)

第2代:在一次以上的垃圾回收后仍然没有被回收的对象。

注:0,1代被称为暂时代,垃圾回收过程对于暂时代的处理是不同的。

5. NET1.0-NET3.5的并发垃圾回收:在回收0和1代时挂起所有活动线程,在回收2代时,允许程序继续分配堆上的对象。

       NET4的后台垃圾回收:后台垃圾回收用于非暂时代,而暂时代专用一个后台线程进行回收。

6. System.GC类型:使用静态成员与垃圾回收器进行交互,在创建那些使用非托管资源的类时需要使用System.GC,例如:使用NET调用基于C的API或者非常低级且复杂的COM互操作逻辑。

7.强制垃圾回收:

       a.如果应用程序要进入一段不希望被垃圾回收终端的代码;

       b.应用程序刚刚分配了非常多的对象,你想尽可能多地删除已获得的内存。GC.Collect(可以佩戴参数)(会增加对象的代)+GC.WaitForPendingFinalizers();

8. 类型终结器:从Object继承来的Finalize()其实就是析构函数。在使用非托管资源时有可能需要(原始的操作系统文件句柄等资源) 其中:结构由于是值类型,它通过实现Idisponsable接口来实现析构。

       Finalize()虽然是虚函数,但是却不能通过override去实现,而是像C++析构函数那样去实现。

9.终结队列:当在托管堆上分配对象时,运行库自动确定该对象是否提供析构Finalize()方法,如果是这样,对象被标记为可终结的,同时一个指向这个对象的指针被保存在名为终结队列的内部队列里。

       终结过程:当垃圾回收器要释放一个对象时,先检查终结队列,并将对象从堆上复制到终结可达表的托管结构,下一次垃圾回收将产生另一个线程,为每一个在可达表中的对象调用终结方法。(至少要进行两次垃圾回收)效率很低,本质上是非确定的。

10.        构建可处置对象:实现Idsiposable接口,适合于类和结构,如果类泗洪县了Idisposable,调用Dispose()总是正确的。(例如FileStream虽然调用Close方法,但调用Dispose方法是一样的)    

       If(rw is IDisposable) rw.Dispose();这样调用不用去查SDK。

using(MyResourceWrapper rw = new MyResourceWrapper(),//一个using只能声明一种类型

                  rw2 = newMyResourceWrapper()){// Use rw and rw2 objects. }

       在using代码段中为每一个声明的对象调用Dispose方法,如果试图使用一个没有实现IDisposable的对象会收到编译器错误。(不一定写了手动调用方法,很麻烦的)

11. 在类里既写析构函数,又写Dispose()方法,并在Dispose中调用GC.SuppressFinalize(this);可以保证正确析构。(代码重复)

12. 但是我们正式的方法是(微软提供的方法):

  class MyResourceWrapper : IDisposable  //这是一个模板,太死板,但是可以防止多次析构。

    {

        // Used todetermine if Dispose()

        // hasalready been called.

        privatebool disposed = false;

 

        public void Dispose()

        {

            // Callour helper method.

            //Specifying "true" signifies that

            // theobject user triggered the cleanup.

            CleanUp(true);

 

            // Nowsuppress finalization.

            GC.SuppressFinalize(this);

        }

 

        privatevoid CleanUp(booldisposing)

        {

            // Besure we have not already been disposed!

            if(!this.disposed)

            {

                // Ifdisposing equals true, dispose all

                //managed resources.

                if(disposing)

                {

                    //Dispose managed resources.

                }

                //Clean up unmanaged resources here.

            }

            disposed = true;

        }

 

        ~MyResourceWrapper()

        {

            Console.Beep();

            // Callour helper method.

            //Specifying "false" signifies that

            // the GCtriggered the cleanup.

            CleanUp(false);

        }

 

    }

       弱引用和对象复苏没有分析,自己去分析。

13. 延迟实例化:在代码中添加一个永远不会被使用的特殊成员变量,如果成员变量的初始化需要很大的空间,问起就来了。

       可以手工添加一些代码来确保只有在使用时才创建allSongs对象(如使用工厂方法设计模式)

       但是NET4提供了Lazy<>泛型类来确保使用时创建

PrivateLazy<AllTracks> allSongs=new Lazy<AllTracks>();

14. 当AllTracks包含其他构造函数,并且你想调用他们,如果建立Lazy<>变量时还有额外的工作要做,又会怎样呢?幸好Lazy<>类允许指定一个泛型委托作为可选参数,类型为System.Func(),它所指向的方法的返回值类型和Lazy<>变量所创建的类型是相同的。

private Lazy<AllTracks> allSongs = new Lazy<AllTracks>( (这里可以指定参数,而不仅仅是默认构造函数) => {

    Console.WriteLine("Creating AllTracks object!");

     return new AllTracks();});  //注意这里的构造函数和Lamda表达式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值