谈到Dispose,首先须要理解C#的资源数据库
调用的是微软类库或者第三方类库,通常类库会提供释放的方法,即约定为Dispose,调用便可。api
每一个类库固然能够提供各自释放资源的方法,好比close()、close()、release()、clear()等等。网络
但为了统一,微软提供了IDispose接口,其中只声明了一个void的Dispose()方法。并且还为实现了IDispose接口的类提供了using释放资源的语法糖。ide
看代码:函数
namespace System { [ComVisible(true)] public interface IDisposable { //执行与释放或重置非托管资源关联的应用程序定义的任务。 void Dispose(); } }
好比咱们进行一个给图片加水印的功能,使用System.Drwing类库中的Image对象。写代码的时候,咱们既不手动调用Dispose方法,也不使用using语法。那么Image对象就一直会留在内存中吗?
固然不会,Image类有析构函数,在其中调用了Dispose方法。性能
上源码:this
public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (this.nativeImage != IntPtr.Zero) { try { SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(this, this.nativeImage)); } catch (Exception ex) { if (ClientUtils.IsSecurityOrCriticalException(ex)) { throw; } } finally { this.nativeImage = IntPtr.Zero; } } } ~Image() { this.Dispose(false); }
既然最终析构函数中会释放资源,那么咱们是否是不必手动释放了呢?
这就要说说析构函数了spa
当一个类的实例被GC回收的时候,最终调用的方法。它和构造函数正好相反,后者是在类的实例初始化时调用。线程
它的写法是这样子的:code
class Car { ~Car() // finalizer { // cleanup statements... } }
隐式的调用了基类的Finalize方法,因此等价下面的写法:
protected override void Finalize() { try { // Cleanup statements... } finally { base.Finalize(); } }
Finalize操做呢,有如下限制:
(来源:https://docs.microsoft.com/en-us/dotnet/api/system.object.finalize?view=netframework-4.8 )
简单理解就是Finalize操做由GC决定,回收的时间不定、顺序不定、线程不定。因此析构函数中调用Dispose只是一个保险措施,并不能代替手动释放资源。
好比数据库链接,你打开链接不及时释放,很快就没法链接新的数据库了。而此时GC有可能还未执行析构函数。
固然,析构函数在GC回收的时候,还会由于垃圾回收机制有其余性能问题,详细咱们在垃圾回收机制的文章中讲。
(参考:https://www.viva64.com/en/b/0437/ )
因此,到目前为止,咱们清楚的知道,对于非托管资源的使用,必定要记得释放资源。
咱们给被人提供类库的时候,也明白了到底何时须要实现IDispose接口了。
固然,Dispose的实现已然有套路了,称之为Dispose模式,如下是示例:
using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; class BaseClass : IDisposable { // Flag: Has Dispose already been called? bool disposed = false; // Instantiate a SafeHandle instance. SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true); // Public implementation of Dispose pattern callable by consumers. public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) { handle.Dispose(); // Free any other managed objects here. // } disposed = true; } }
哟,刚才上面的Image类里面不就是这么写的么? 是呀!