Finalizable、Disposable

Finalizable可终结对象

  从内存中删除一个对象前,垃圾回收器会调用对象的Finalize()方法(如果支持的话)。

   Finalize()的调用将(最终)发生在一次“自然”垃圾回收或应用程序通过GC.Collect()强制回收的过程中。另外,当承载应用程序的应用程序域AppDomain从内存中卸载时,会自动调用类型的终结器方法。

  大多数C#类都不需要显式的清理逻辑。因为这些类型使用的其他托管对象,最终都会被垃圾回收。只有在使用非托管资源时(操作系统文件句柄、原始的非托管数据库连接或其他非托管资源),才可能需要设计一个在用完后清理自身的类。

  所以,重写Finalize()的唯一原因是,C#类通过PInvoke或复杂的COM互操作性任务使用了非托管资源

  虽然Finalize()为System.Object的虚方法,但是在实现其方法时,却不能使用override关键字,而是使用类似C++的析构函数。

  Finalize()方法的作用是保证用户在没有显示释放系统资源的情况下,GC在调用Collector方法回收内存之前,被CLR执行的一段保险代码。.NET对象能在垃圾回收时清除非托管资源。如果创建了一个不使用非托管实体的类型,终结是没有用的。

 Disposable可处置对象

  一个类如果提供IDisposable接口,就是假设对象不的用记不在使用这个对象时,会在这个对象引用离开作用域之前手工地调用Dispose()。这样对象可以执行任何必要的非托管资源的清理,而且不会在有将对象放在终结队列上导致的性能损失,也不必等垃圾回收器触发类的终结逻辑。

  Dispose()方法不只负责释放一个对象的非托管资源,还调用它包含的其它任何对象的Dispose()方法。与Finalize()不同Dispose()中与其它托管对象的通信是安全的。因此,当对象的用户调用这个方法时,对象仍然在托管堆上,并可以访问所有其它分配在堆上的对象。

  如果对象支持IDisposable,总是要对任何直接创建的对象调用Dispose()方法。应该认为,如果类设计者选择支持Dispose()方法,这个类型就需要执行清理工作。

  使用Disposable应该注意:

  1、如果资源在之前就已经释放过,就应该使用GC.SuppressFinalize(this)方法通知GC,不要再对该资源进行Finalize操作。

  2、确保重复执行Disposable操作时,程序不会出错。

  Using :可使用using关键字来定义对象的生存周期。如果超出using的范围后,且系统实现了IDisposble接口,系统会自动调用Dispose()方法。

体会

  GC的垃圾回收会自动的清理托管资源,但不会自动清理非托管资源。但是GC在清理资源的时候会调用Finalize()方法。所以,为了却保非托管资源的清理,就将非托管资源清理的操作放到 Finalize()方法中。从而使得当GC开始清理时,非托管资源也得到清理。

  但是,GC的垃圾回收是发行在托管堆没有足够的内存来分配时发生,不受程序员的控制。由于非托管资源是非常宝贵的,所以应该把它们尽快清除。考虑到在清理该对象的同时,还需要清理该对象包含的其它任何对象,所以使用了IDisposable接口。这样使得对象间建立一种默契——清理方法都叫作Dispose。同时还有using配合使用。

  但是Dispose方法和Finalize方法一样,只是提供了一种对象清理的机制,该方法并不完成对象的清理工作。所以,需要在该方法中实现对象清理的代码。

Code


原文地址:https://www.cnblogs.com/76674718/p/1596303.html