有哪些数据类型,对于调用Dispose()是非常重要的呢?关于GDI我知道的有:
Graphics
Pen
SolidBrush
Font
Bitmap下面这些不需要:
Point
Size
Rectangle
Color有两个问题:
1.以前我经常这样写:        public void FangFa001(Font font)
        {
            //内容
        }
            //调用
            FangFa001(new Font("Arial",12));这种直接new的Font最后会自动Dispose()吗?2.还有哪些对于调用Dispose()是非常重要的数据类型?请诸位列举。

解决方案 »

  1.   

    .Net有垃圾回收机制,一般情况下不需要调用Dispose()来释放对象吧,对象生存周期结束后都会自动被处理掉
    给个链接作参考
    http://www.yesky.com/20030311/1656401.shtml
      

  2.   

    实现此方法时,可通过在包容层次结构中传播调用来确保释放所有保持的资源。例如,如果对象 A 分配对象 B,而对象 B 又分配对象 C,那么 A 的 Dispose 实现必须对 B 调用 Dispose,而 B 反过来必须对 C 调用 Dispose。如果一个对象的基类实现 IDisposable,该对象还必须调用其基类的 Dispose 方法。如果某对象的 Dispose 方法被调用一次以上,则该对象必须忽略第一次调用后的所有调用。如果对象的 Dispose 方法被多次调用,该对象一定不要引发异常。除 Dispose 之外的实例方法在资源已释放时会引发 ObjectDisposedException。用户可能期望资源类型使用特定的约定来表示已分配状态和已释放状态。流类即是这样一种示例,传统上认为它们要么打开要么关闭。具有此种约定的类的实施者可能选择实现具有自定义名称(如“Close”)的公用方法来调用 Dispose 方法。因为 Dispose 方法必须显式进行调用,所以,实现 IDisposable 的对象还必须实现一个终结器,以便在未调用 Dispose 时处理释放资源问题。默认情况下,垃圾回收器会在回收一个对象的内存之前自动调用该对象的终结器。然而,在调用 Dispose 方法后,通常不需要垃圾回收器调用已释放对象的终结器。为防止自动终止,Dispose 实现可以调用 GC.SuppressFinalize 方法。using System;
    using System.ComponentModel;// The following example demonstrates how to create
    // a resource class that implements the IDisposable interface
    // and the IDisposable.Dispose method.public class DisposeExample
    {
        // A base class that implements IDisposable.
        // By implementing IDisposable, you are announcing that 
        // instances of this type allocate scarce resources.
        public class MyResource: IDisposable
        {
            // Pointer to an external unmanaged resource.
            private IntPtr handle;
            // Other managed resource this class uses.
            private Component component = new Component();
            // Track whether Dispose has been called.
            private bool disposed = false;        // The class constructor.
            public MyResource(IntPtr handle)
            {
                this.handle = handle;
            }        // Implement IDisposable.
            // Do not make this method virtual.
            // A derived class should not be able to override this method.
            public void Dispose()
            {
                Dispose(true);
                // This object will be cleaned up by the Dispose method.
                // Therefore, you should call GC.SupressFinalize to
                // take this object off the finalization queue 
                // and prevent finalization code for this object
                // from executing a second time.
                GC.SuppressFinalize(this);
            }        // Dispose(bool disposing) executes in two distinct scenarios.
            // If disposing equals true, the method has been called directly
            // or indirectly by a user's code. Managed and unmanaged resources
            // can be disposed.
            // If disposing equals false, the method has been called by the 
            // runtime from inside the finalizer and you should not reference 
            // other objects. Only unmanaged resources can be disposed.
            private void Dispose(bool disposing)
            {
                // Check to see if Dispose has already been called.
                if(!this.disposed)
                {
                    // If disposing equals true, dispose all managed 
                    // and unmanaged resources.
                    if(disposing)
                    {
                    // Dispose managed resources.
                    component.Dispose();
                    }
                 
                    // Call the appropriate methods to clean up 
                    // unmanaged resources here.
                    // If disposing is false, 
                    // only the following code is executed.
                    CloseHandle(handle);
                    handle = IntPtr.Zero;            
                }
                disposed = true;         
            }        // Use interop to call the method necessary  
            // to clean up the unmanaged resource.
            [System.Runtime.InteropServices.DllImport("Kernel32")]
            private extern static Boolean CloseHandle(IntPtr handle);        // Use C# destructor syntax for finalization code.
            // This destructor will run only if the Dispose method 
            // does not get called.
            // It gives your base class the opportunity to finalize.
            // Do not provide destructors in types derived from this class.
            ~MyResource()      
            {
                // Do not re-create Dispose clean-up code here.
                // Calling Dispose(false) is optimal in terms of
                // readability and maintainability.
                Dispose(false);
            }
        }
        public static void Main()
        {
            // Insert code here to create
            // and use the MyResource object.   
        }
    }
      

  3.   

    《利用C#实现标准的Dispose模式》
         本文讲解的是你在建立包含内存以外资源的类型,特别是处置非内存资源的时候,如何编写自己的资源管理代码。
       我们已经知道了处置那些占用非受控(unmanaged)资源的对象的重要性,现在应该编写资源管理代码来处置那些包含非内存资源的类型了。整个.NET框架组件都使用一个标准的模式来处理非内存资源。使用你建立的类型的用户也希望你遵循这个标准的模式。标准的处理模式的思想是这样的:当客户端记得的时候使用IDisposable接口释放你的非受控资源,当客户端忘记的时候防护性地使用终结器(finalizer)。它与垃圾收集器(Garbage Collector)一起工作,确保只在必要的时候该对象才受到与终结器相关的性能影响。这是处理非受控资源的一条很好的途径,因此我们应该彻底地认识它。    类层次体系中的根基类(root base class)必须实现IDisposable接口以释放资源。这个类型还必须添加一个作为防御机制的终结器。所有这些程序都把释放资源的工作委托给一个虚拟的方法,衍生的类可以根据自己的资源管理需求来重载该方法。只要衍生的类必须释放自己的资源,并且它必须调用该函数的基类版本的时候,它才需要重载这个虚拟方法。    开始的时候,如果你的类使用了非内存资源,它就必须含有一个终结器。你不能依赖客户端总是调用Dispose()方法。因为当它们忘记这样做的时候,你就面临资源泄漏的问题。没有调用Dispose是它们的问题,但是你却有过失。用于保证非内存资源被正确地释放的唯一途径是建立终结器。    当垃圾收集器运行的时候,它立即从内存中删除所有不带终结器的垃圾对象。所有带有终结器的对象仍然存在于内存中。这些对象都被添加到终结队列,垃圾收集器引发一个新线程,周期性地在这些对象上运行终结器。在这些终结程序线程完成自己的工作之后,就可以从内存中删除垃圾对象了。需要终结的对象在内存中停留的时间比没有终结器的对象停留的时间长很多。但是你别无选择。如果要使程序有防护性,在类型包含非受控资源的时候,你必须编写一个终结器。但是也不用担心性能问题。下一步确保了客户端避免与终结相关的性能开销。 
    实现IDisposable接口是一种标准的途径,它通知用户和运行时系统持有资源的对象必须及时地释放。IDisposable接口仅仅包含一个方法: public interface IDisposable 

      void Dispose( ); 
    }     你对IDisposable.Dispose()方法的实现(implementation)负责下面四个事务:    1、释放所有的非受控资源。    2、释放所有的受控资源(包括未解开事件)。    3、设置标志表明该对象已经被处理过了。你必须在自己的公共方法中检查这种状态标志并抛出ObjectDisposed异常(如果某个对象被处理过之后再次被调用的话)。    4、禁止终结操作(finalization)。你调用GC.SuppressFinalize(this)来完成这种事务。    通过实现IDisposable接口你完成了两个事务:你为客户端及时地释放自己持有的所有受控资源提供了机制;你为客户端提供了一种释放非受控资源的标准途径。这是一个很大的进步。当你在类型中实现了Idisposable接口的时候,客户端可以避免终结操作的开销,你的类就成为.NET世界中的"良民"了。    但是在你建立的这种机制中仍然存在一些问题。怎样在衍生类清理自己资源的时候同时也让基类能够清理资源?如果衍生类重载了终结操作,或者添加了自己的IDisposable实现,那么这些方法必须调用基类,否则,基类就不能正确地进行清理操作。同样,finalize(终结操作)和Dispose参与分担了一些相同的职责。Finalize方法和Dispose方法的代码几乎相同。而且在重载接口函数后并不像你预料的那样工作。标准的Dispose模式中的第三个方法是一个受保护的虚拟辅助函数,它分解出这些共同的事务,并给衍生类添加一个用于释放资源的"钩子(hook)"。基类包含了核心接口的代码。作为对Dispose()或终结操作的响应,该虚拟函数为衍生类清除资源提供了"钩子": protected virtual void Dispose( bool isDisposing );     这个重载的方法实现支持finalize和Dispose的必要事务,由于它是虚拟的,它为所有的衍生类提供了一个入口点。衍生类可以重载这个方法,为清除自己的资源提供适当的实现,同时还可以调用基类版本。当isDisposing为真(true)的时候,你可以清除受控和非受控资源,当isDisposing为假(false)的时候,你只能清除非受控资源。在这两种情况下,你都可以调用基类的Dispose(bool)方法,让它清除自己的资源。
       下面有一个简短的例子,它演示了你在实现这种模式的时候所提供的代码框架。MyResourceHog类演示了实现IDisposable接口、终结器的代码,并建立了一个虚拟的Dispose方法: public class MyResourceHog : IDisposable 

      // 已经被处理过的标记 
      private bool _alreadyDisposed = false; 
      // 终结器。调用虚拟的Dispose方法 
      ~MyResourceHog() 
      { 
       Dispose( false ); 
      }   // IDisposable的实现 
      // 调用虚拟的Dispose方法。禁止Finalization(终结操作) 
      public void Dispose() 
      { 
       Dispose( true ); 
       GC.SuppressFinalize( true ); 
      }   // 虚拟的Dispose方法 
      protected virtual void Dispose( bool isDisposing ) 
      { 
       // 不要多次处理 
       if ( _alreadyDisposed ) 
        return; 
       if ( isDisposing ) 
       { 
        // TODO: 此处释放受控资源 
       } 
       // TODO: 此处释放非受控资源。设置被处理过标记 
       _alreadyDisposed = true; 
      } 
    }     如果衍生类需要执行另外的清除操作,它应该实现受保护的Dispose方法: public class DerivedResourceHog : MyResourceHog 

      // 它有自己的被处理过标记 
      private bool _disposed = false;   protected override void Dispose( bool isDisposing ) 
      { 
       // 不要多次处理 
       if ( _disposed ) 
        return; 
       if ( isDisposing ) 
       { 
        // TODO: 此处释放受控资源 
       } 
       // TODO: 此处释放所有受控资源    // 让基类释放自己的资源。基类负责调用GC.SuppressFinalize( ) 
       base.Dispose( isDisposing );    // 设置衍生类的被处理过标记 
      _disposed = true; 
      } 
    }     请注意,基类和衍生类都包含该对象的被处理过(disposed)标记。这纯粹是起保护作用。复制这个标记可以封装构成某个对象的所有类释放资源时产生的任何可能的错误。    你必须编写防护性的Dispose和finalize。对象的处理可以按任意次序进行,你可能会遇到在调用自己类型的成员对象的Dispose()方法之前,该对象已经被处理过了。你不应该认为这是问题,因为Dispose()方法会被多次调用。如果它在已经被处理过的对象上被调用,它就不执行任何事务。Finalizer(终结器)也有类似的规则。如果你引用的对象仍然存在于内存中,你就没有必要检查空引用(null reference)。但是,你引用的任何对象都可能被处理了,它也可能已经被终结了。    这为我带来了与处理或清除相关的任何方法的最重要的建议:你应该仅仅释放资源,在dispose方法中不要执行任何其它操作。如果你在Dispose或finalize方法中执行其它操作,都可能给对象的生命周期带来严重的不良影响。对象在被构造的时候才"出生",当垃圾收集器收回它们的时候才"死亡"。当你的程序再也不能访问它们的时候,你可以认为它们处于"昏睡"状态。如果你不能到达(reach)某个对象,你就不能调用它的方法,对于所有的意图和目的来说,它是死的。但是带有终结器的对象被宣布死亡之前还有最后一口气。终结器除了清理非受控资源之外不应该执行其它任何操作。如果某个终结器由于什么原因使某个对象又可以到达了,那么该对象就恢复(resurrected)了。即使它是从"昏睡"状态醒来的,它也是"活着"的。下面是一个很明显的例子: public class BadClass 

      // 保存某个全局对象的引用 
      private readonly ArrayList _finalizedList; 
      private string _msg;   public BadClass( ArrayList badList, string msg ) 
      { 
       // 缓冲该引用 
       _finalizedList = badList; 
       _msg = (string)msg.Clone(); 
      }   ~BadClass() 
      { 
       // 把该对象添加到列表中。这个对象是可到达的,不再是垃圾了。它回来了! 
       _finalizedList.Add( this ); 
      } 
    }     当某个BadClass对象执行自己的终结器的时候,它向全局列表上添加了对自己的引用。这仅仅使自己可到达了,它活了过来!但是这样操作所带来的问题使任何人都会感到胆怯。该对象已经被终结了,因此垃圾收集器相信不用再次调用它的终结器了。你真的需要终结一个被恢复的对象的时候,终结操作却不会发生了。其次,你的一些资源可能不能用了。GC不会把终结器队列中的对象可以到达的任何对象从内存中移除,但是它可能已经终结了这些对象。如果是这样的话,那些对象一定不能再次使用了。尽管BadClass的成员仍然存在于内存中,它们却像被处理过或被终结了一样。在C#语言中没有控制终结次序的途径。你不能使这种构造工作更可靠。不要尝试!    除了学院的练习作业之外,我从来没有见到过如此明显地使用被恢复对象的代码。但是我看到有些代码有这个倾向,它们在终结器中试图执行某些实际工作,当终结器调用的某些函数保存了对该对象的引用的时候,它就正在把对象变成活动的状态。原则上我们必须非常仔细地检查finalizer和Dispose方法中任何代码。如果有些代码除了释放资源之外还执行了其它的操作,我们就需要再检查一次。这些操作在未来可能引起程序bug。请移除这些操作,并确保finalizer和Dispose()方法只释放资源,不作其它任务事务。    在受控环境中,你不必为自己建立的每个类型编写终结器,你只需要为存储非受控类型,或者包含了实现IDisposable接口的成员的类型编写终结器。即使你只需要Disposable接口,不需要finalizer,也应该同时实现整个模式。否则,你会使衍生类的标准Dispose思想的实现变得很复杂,从而限制了衍生类的功能。请遵循前面谈到的标准的Dispose思想,这将使你、你的类的用户、从你的类型建立衍生类的用户的生活更加轻松。 
      

  4.   

      对于实现IDisposable的许多类来说.,Dispose{)方法会在析构函数中自动调用。有人可能认为,这样就不必调用Dispose)了,但事实并非如此。原因是只有在垃圾回收器(Gc)调用了析构函数时,我们才不必调用Dispose(),但不能确保GC何时运行。不清楚的问题,请别误导别人
      

  5.   

    不应该针对类型, 而是应该针对情况。例如 Bitmap ,是不是一定要在用了之后显示释放呢。如果 Bitmap 仅是在 Onload 的时候 DrawImage 一次, Dispose 就变得多此一举。例如 DataTable, 是不是从来都不用管呢, 通常就是只有几百上千条记录, 当然不用理会。但是要是里面存有几十万条记录呢。
      

  6.   

    有哪些数据类型,对于调用Dispose()是非常重要的呢? 
    =======
    并没有什么数据类型实现了dispose却对调用不重要的类呀。
    用了非托管资源的代码一般可以手工调用一下Dispose。不过确实很难区分哪些是非托管资源,一般可以理解成只是用与运算的都是托管的,用到操作系统的东西就会有非托管资源。你可以在ide里,按F2类浏览器,找到IDisposable接口,看一下派生出来的那些类,都是可以调用dispose的。
      

  7.   


    说的很有道理,
    看《C#入门经典》,说“对创建的Font对象调用Dispose{)或使用using块是很重要的,否则应用程序就可能耗尽”
    那么,我的第一个问题“FangFa001(new Font("Arial",12));”这样写违反了上面的规则了吗,还是这样new的在方法FangFa001结束后能自动Dispose?还是必须写成"Font font =new Font("Arial",12);FangFa001(font);font.Dispose{)”
    第二个问题改成“还有哪些在创建之后,对于调用Dispose()是非常重要的数据类型?请诸位列举。”
    【我是还珠楼主】
      

  8.   


    GC 的运行时间是可以控制的, 用 GC.Collect 就可以。但是收不收你想它收的东西呢, 那就看 GC  的心情了
      

  9.   

    在“Font font =new Font("Arial",12);”之后,
    如下三种操作方法:
    1.不管了,让gc自己控制
    2.font=null
    3.font.Dispose()
    实际上运行起来,对性能的影响有多大?