zoukankan      html  css  js  c++  java
  • C#中标准Dispose模式的实现与使用(条目17 实现标准的销毁模式)

    实现了Dispose模式与实现了IDisposable接口的区别就是:IDisposable的实现的可靠性(释放相关资源)要靠编程人员来解决(你确信你从来都一直调用了Dispose(Close)方法吗?),而实现了Dispose模式后,当编程人员没有主动调用Dispose方法时,会由终结器来调用(有些时候编程人员想主动调用也调用不了,比如远程连上来的TcpChannel,客户端断开时,服务端只能由终者器调用)。

    Dispose模式()的实现需要以下4个步骤:
    1. 释放所有非托管资源;
    2. 释放所有托管资源,包括释放事件监听程序;
    3. 设计一个状态标志(IsDisposed),表示该对像已经被销毁。若是在销毁后再次调用对像的公有方法,那么应该抛出ObjectDisposed异常;
    4. 跳过终者操作,调用CG.SuppressFinalize(this)即可。

    注:
    ------------------
    托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象;
    非托管资源:不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等;

    用实现来说明。
    EXAMPLE CODE:

    using System;
    
    namespace CS.DesignPatterns
    {
        /// <summary>
        /// 示例
        /// </summary>
        public class DisposePatternSample:IDisposable
        {
            private bool _isDisposed;//是否已释放了资源,true时方法都不可用了。
    
            public DisposePatternSample()
            {
                _isDisposed = false;
            }
    
            public void MethodSample()
            {
                if(_isDisposed)
                    throw new ObjectDisposedException("inner resource is disposed.");
                Console.WriteLine("MethodSample is called.");
            }
    
            /// <summary>
            /// 为继承类释放时使用
            /// <remarks>
            /// Note:这儿为什么要写成虚方法呢?
            /// 1. 为了让派生类清理自已的资源。将销毁和析构的共同工作提取出来,并让派生类也可以释放其自已分配的资源。
            /// 2. 为派生类提供了根据Dispose()或终结器的需要进行资源清理的必要入口。
            /// </remarks>
            /// </summary>
            /// <param name="isDisposing"></param>
            protected virtual void Dispose(bool isDisposing)
            {
                if(_isDisposed)return;
                
                if (isDisposing)
                {
                    //释放托管资源
                    //(由CLR管理分配和释放的资源,即由CLR里new出来的对象)
                    //TODO: other code
                }
    
                //释放非托管资源
                //(不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等)
                //TODO: other code
    
                _isDisposed = true;
            }
    
            #region IDisposable 成员
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            #endregion
    
            ///// <summary>
            ///// 如果没有非托管资源,不要实现它
            ///// </summary>
            //~DisposePatternSample()
            //{
            //    Dispose(false);
            //}
        }
    
    
        public class DrivedDisposePatternSample : DisposePatternSample
        {
            private bool _isDisposed = false; //各类维护自已的释放状态,把可能出现的错误限制在类本身
    
            /// <summary>
            /// 子类清理自已的资源时使用
            /// </summary>
            /// <param name="isDisposing"></param>
            protected override void Dispose(bool isDisposing)
            {
                if(_isDisposed)return;
                if (isDisposing)
                {
                    //释放托管资源
                    //(由CLR管理分配和释放的资源,即由CLR里new出来的对象)
                    //TODO: other code
                }
    
                //释放非托管资源
                //(不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等)
                //TODO: other code
    
                //基类释放资源
                //基类负责调用GC.SuppressFinalize()
                base.Dispose(isDisposing);
    
                _isDisposed = true;
            }
    
            ///// <summary>
            ///// 如果没有非托管资源,不要实现它
            ///// </summary>
            //~DrivedDisposePatternSample()
            //{
            //    Dispose(false);
            //}
    
        }
    
    }

     

    上述的代码并没有使用析构方法,这是因为上述的代码并没有使有非托管资源(永远不会调用Dispose(false))方法。注意:除非你调用了非托管资源,否则不要实现析构方法。即使析构器永远不会被调用,它本身也会极大的影响类型的性能。不要画蛇添足。不过这个模式却不能改变,因为你的派生类可能会用到非托管的资源。

    重要的建议:只能在Dispose方法中释放资源,不得进行其它操作(如果一不小心的其它操作,让本该死亡的对象起死回生,哼哼~~~~)。

    请遵守Dispose标准模式的实现,这会节省你,你的类型使用者,你的类型的派生者的大量的时间。

  • 相关阅读:
    clip属性,截取你想要显示的图片
    select背景灰色
    [转]ShowModal() = mrOk
    【转】Delphi-Unit文件结构
    析构方法
    [转]Delphi 7连接MySql /MariaDB
    MySQL/Mariadb遇见的问题
    更换数据库
    FlameRobin
    FireBird初使用
  • 原文地址:https://www.cnblogs.com/atwind/p/3447296.html
Copyright © 2011-2022 走看看