在.NET中,每一种类型都代表一种资源,而资源分为托管资源与非托管资源两类:

1) 托管资源:由CLR分配和释放的资源,即从CLR中new声明的对象,一般指托管内存。托管资源进一步又可分为:

  a、普通类型托管资源:如int、String、float等;

  b、非普通类型托管资源:继承了IDispose接口的类实例化后对应的对象,此类资源被GC回收时需经2个步骤,会降低系统性能,因此在实现Dispose方法时需手动清理;

2) 非托管资源:不受CLR管理的对象,如Windows内核对象、文件、数据库连接、套接字、COM对象等;

注:1) 继承IDispose接口的类实例化的对象不是非托管资源,个人理解:非托管资源几乎无法在程序中自定义。

      2) 个人理解,数据库连接如SqlConnection本身是托管资源,只是内部包含了非托管资源-数据库连接的系统资源。

--------------------------------------------------------

  如果我们定义的类型使用到了非托管资源或非普通类型托管资源,就需要显示地释放托管资源,实现方法是让类型继承IDispose接口,并实现接口中的Dispose方法。标准的Dispose模式实现方式如下:

//演示需要,自定义非普通托管类型
class MyResource : IDisposable
{
    public void Dispose(){ }
}

public class SampleClass : IDisposable
{
    //演示创建一个非托管资源
    private IntPtr nativeResource = Marshal.AllocHGlobal(100);
    //演示创建一个非普通类型托管资源,MyResource实现了接口IDisposable,是一个非普通类型的托管资源
    private MyResource myResource = new MyResource();
    //演示创建一个普通类型的托管资源
    private String name = "hduhans";

    private bool disposed = false;

    /// <summary>
    /// 实现IDisposable中的Dispose方法
    /// </summary>
    public void Dispose()
    {
        //必须为true,显示释放所有资源
        Dispose(true);
        //通知垃圾回收机制不再调用终结器(析构器),也就是GC不会调用~SampleClass()方法
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// 必须,防止程序员忘记了显式调用Dispose方法,这时可由GC来回收并释放非托管资源
    /// 注意在析构函数中不允许释放托管资源,因为GC在调用析构函数前可能已经释放了托管资源,此处再释放可能会引发异常
    /// </summary>
    ~SampleClass()
    {
        //必须为false
        Dispose(false);
    }

    /// <summary>
    /// 如果子类继承当前类型并实现了自己的Dispose方法,必须调用父类的Dispose方法来释放父类中的资源,调用:base.Dispose(disposing)
    /// </summary>
    /// <param name="disposing"></param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
        {
            return;
        }
        if (disposing)
        {
            // 清理非普通类型(继承IDispose接口)的托管资源,普通类型的托管资源(此例中name)不需要手动清理,GC会自动清理
            if (myResource != null)
            {
                myResource.Dispose();
                myResource = null;
            }
        }
        // 清理非托管资源
        if (nativeResource != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(nativeResource);
            nativeResource = IntPtr.Zero;
        }
        //让类型知道自己已经被释放
        disposed = true;
    }
}
View Code

相关文章:

  • 2021-10-03
  • 2021-06-14
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-01-22
  • 2021-08-23
  • 2022-12-23
  • 2021-05-22
  • 2022-02-23
  • 2022-12-23
相关资源
相似解决方案