C# 托管非托管资源释放

1、C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源。

2、C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析构函数中,同时会实现IDipose接口。

3、IDipose作用是可以通过using手动提前释放,节约宝贵的资源。

4、在C#中,凡是继承了IDisposable接口的类,都可以使用using语句,从而在超出作用域后,让系统自动调用Dispose()方法。 一个资源安全的类,都实现了IDisposable接口和析构函数。提供手动释放资源和系统自动释放资源的双保险。

5、类似FileStream,会同时实现IDipose,及定义~FileStream(),~FileStream()作用是使用者没有调用IDipose,在GC回收时再回收非托管资源,否则非托管资源只有在程序停止之后才会释放。

析构函数只能由垃圾回收器调用。Despose()方法只能由类的使用者调用。

总结区分托管资源和非托管资源

(1)托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,例如程序中分配的对象,作用域内的变量等。 

(2)非托管资源是CLR不能控制或者管理的部分,这些资源有很多,比如文件流,数据库的连接,系统的窗口句柄,打印机资源 等,这些资源一般情况下不存在于Heap(内存中用于存储对象实例的地方)中。

托管资源:从文字上看就是托付给别人管理,就像.NET的CLR,java的jvm

例子:

public class SourceManager : IDisposable
{
    private bool disposed = false;
    //非托管资源
    private IntPtr handle;
    //托管资源
    FileStream fs = null;
    public SourceManager()
    {
    }

    //由垃圾回收器调用,释放非托管资源
    ~SourceManager()
    {
        //GC调用,终结 
        Dispose(false);// 释放非托管资源
    }

    //实现接口方法
    //由类的使用者,在外部显示调用,释放类资源
    public void Dispose()
    {
        Dispose(true);// 释放托管和非托管资源

        //将对象从垃圾回收器链表中移除,
        // 从而在垃圾回收器工作时,只释放托管资源,而不执行此对象的析构函数
        GC.SuppressFinalize(this);
    }

    //参数为true表示释放所有资源,只能由使用者调用
    //参数为false表示释放非托管资源,只能由垃圾回收器自动调用
    //如果子类有自己的非托管资源,可以重载这个函数,添加自己的非托管资源的释放
    //但是要记住,重载此函数必须保证调用基类的版本,以保证基类的资源正常释放
    protected virtual void Dispose(bool disposing)
    {
        // 如果资源未释放 这个判断主要用了防止对象被多次释放
        if (!this.disposed)
        {
            if (disposing && fs != null)
            {
                // 释放托管资源
                fs.Dispose();
            }

            //释放非托管资源
            //...
            handle = IntPtr.Zero;

            disposed = true; // 标识此对象已释放
        }

    }
}
原文地址:https://www.cnblogs.com/valor-xh/p/6732384.html