首页 > 学院 > 开发设计 > 正文

编写高质量代码改善C#程序的157个建议——建议46:显式释放资源需继承接口IDisposable

2019-11-14 14:05:38
字体:
来源:转载
供稿:网友

建议46:显式释放资源需继承接口IDisposable

C#中的每一个类型都代表一种资源,资源分为两类:

托管资源:由CLR管理分配和释放的资源,即从CLR里new出来的对象。

非托管资源:不受CLR管理的对象,如Windows内核对象,或者文件、数据库连接、套接字、COOM对象等。

如果我们的类型使用了非托管资源,或者需要显示地释放托管资源,那么就需要让类型继承接口IDisposable,这毫无例外。这相当于告诉调用者,类型资源是需要显示释放资源的,你需要调用类型的Dispose方法。

 

一个标准的继承了IDisposable接口的类型应该像下面这样去实现,这种实现我们称为Dispose模式:

    public class SampleClass : IDisposable    {        //演示创建一个非托管资源        PRivate IntPtr nativeResource = Marshal.AllocHGlobal(100);        //演示创建一个托管资源        private AnotherResource managedResource = new AnotherResource();        private bool disposed = false;        /// <summary>        /// 实现IDisposable中的Dispose方法        /// </summary>        public void Dispose()        {            //必须为true            Dispose(true);            //通知垃圾回收机制不再调用终结器(析构器)            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 (managedResource != null)                {                    managedResource.Dispose();                    managedResource = 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");            }            //省略        }    }    class AnotherResource : IDisposable    {        public void Dispose()        {        }    }

继承IDisposable接口也为实现语法糖using带来了便利。如:

using (SampleClass cl = new SampleClass()){    //省略}

等价于:

SampleClass cl;try{    cl == new SampleClass();    //省略}finally{    cl.Dispose();}

如果存在两个类型一致的对象,using还可以这样使用:

using (SampleClass c1 = new SampleClass(),c2=new SampleClass()){  //省略}

如果两个类型不一致,则可以这样使用:

using (SampleClass c1 = new SampleClass())using (SampleAnotherClass c2 = new SampleAnotherClass()){    //省略}

 

 

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表