【读书笔记】编写高质量代码改善C# 建议46-52 (⭐Dispose模式)

46、显示释放资源需继承接口IDisposable

class SampleClass : IDisposable
{
    //演示创建一个非托管资源
    private IntPtr nativeResource = Marshal.AllocHGlobal(100);
    //演示创建一个托管资源
    private AntherResource manageResource = new AntherResource();
    private bool disposed = false;

    /// <summary>
    /// 实现IDisposable中的Dispose方法
    /// </summary>
    public void Dispose()
    {
        //必须为true
        Dispose(true);
        //通知gc不再调用终结器(析构器)
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// 不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如C++)的规范
    /// </summary>
    public void Close()
    {
        Dispose();
    }

    /// <summary>
    /// 必需的,放置程序员忘记了显示调用Dispose方法
    /// </summary>
    ~SampleClass()
    {
        //必须为false
        Dispose(false);
    }

    /// <summary>
    /// 非密封类修饰用protected virtual
    /// 密封类修饰用private
    /// </summary>
    /// <param name="disposing"></param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
        {
            return;
        }
        if (disposing)
        {
            //清理托管资源
            if(manageResource != null)
            {
                manageResource.Dispose();
                manageResource = null;
            }
        }
        //清理非托管资源
        if(nativeResource != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(nativeResource);
            nativeResource = IntPtr.Zero;
        }
        //让类型知道自己已经被释放了
        disposed = true;
    }

    public void SamplePublicMethod()
    {
        if (disposed)
        {
            throw new ObjectDisposedException("SampleClass", "SampleClass is disposed");
        }
    }
}

47、即使提供了显示释放方法,也应该在析构函数里面提供隐式清理

如上面代码所写,防止忘记调用

48、Dispose方法应允许被多次调用而不抛异常

可能手动调用完,终结器又调用了一次,写法如上面的代码

49、在Dispose模式中应提取一个受保护的虚方法

50、在Dispose模式中应区别对待托管资源和非托管资源

51、具有可释放字段的类型或拥有非托管类型资源的类型应该是可释放的

也就是说如果A类包含了非托管资源,B类组合了A类,那么B类也应该实现Dispose模式

52、及时释放资源

打开文件或者字节流什么的,用using就好了,它会在使用完后后及时释放资源

 

猜你喜欢

转载自blog.csdn.net/qq_33413868/article/details/81489055