Finalize/Dispose/Destructor

本文深入探讨了C#中的资源管理概念,包括Finalize、析构器和Dispose方法的区别与联系,以及如何正确地实现IDisposable接口以确保资源的正确释放。通过具体的代码示例,解释了Dispose模式的实现细节,以及如何避免对象复活导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我总是会搞混这些东西,还是写下来帮助记忆。

Finalize
即Object.Finalize(),C#中不允许使用Finalize,析构器就等价于Finalize。

Destructor
析构器(Destructor)是在对象没有被引用的时候,由CLR自动调用的。
任何包含非托管资源的类都必须定义析构器来释放这些资源,因为它们并不会在对象消亡时自动释放,而托管资源就可以。

Dispose方法
Dispose方法是IDisposable接口的实现方法,Dispose方法并不会被自动调用。

这里还有Dispose(bool)方法的概念,由于类的使用者或许会忘记使用Dispose()方法,并且析构器有可能二次执行析构操作,所以设计Dispose(bool)重载方法来判断并释放托管资源。合理的设计思想是,在Dispose()中使用Dispose(true)来显式释放托管资源和非托管资源,而在析构器中使用Dispose(false),只释放非托管资源(CLR会去自动调用托管资源的析构器)。在Dispose()方法中应使用GC.GC.SuppressFinalize()方法来阻止CLR调用析构器。

至于Close()方法,只是一种习惯名称,一般直接调用Dispose()方法。

来看MSDN里精辟的例子。

//  Design pattern for the base class.
//  By implementing IDisposable, you are announcing that instances
//  of this type allocate scarce resources.
public   class  BaseResource: IDisposable
{
   
//  Pointer to an external unmanaged resource.
    private  IntPtr handle;
   
//  Other managed resource this class uses.
    private  Component Components;
   
//  Track whether Dispose has been called.
    private   bool  disposed  =   false ;

   
//  Constructor for the BaseResource object.
    public  BaseResource()
   {
      
//  Insert appropriate constructor code here.
   }

   
//  Implement IDisposable.
   
//  Do not make this method virtual.
   
//  A derived class should not be able to override this method.
    public   void  Dispose()
   {
      Dispose(
true );
      
//  Take yourself off the Finalization queue 
      
//  to 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.
    protected   virtual   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.
            Components.Dispose();
         }
         
//  Release unmanaged resources. If disposing is false, 
         
//  only the following code is executed.
         CloseHandle(handle);
         handle 
=  IntPtr.Zero;
         
//  Note that this is not thread safe.
         
//  Another thread could start disposing the object
         
//  after the managed resources are disposed,
         
//  but before the disposed flag is set to true.
         
//  If thread safety is necessary, it must be
         
//  implemented by the client.

      }
      disposed 
=   true ;         
   }

   
//  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.
    ~ BaseResource()      
   {
      
//  Do not re-create Dispose clean-up code here.
      
//  Calling Dispose(false) is optimal in terms of
      
//  readability and maintainability.
      Dispose( false );
   }

   
//  Allow your Dispose method to be called multiple times,
   
//  but throw an exception if the object has been disposed.
   
//  Whenever you do something with this class, 
   
//  check to see if it has been disposed.
    public   void  DoSomething()
   {
      
if ( this .disposed)
      {
         
throw   new  ObjectDisposedException();
      }
   }
}

//  Design pattern for a derived class.
//  Note that this derived class inherently implements the 
//  IDisposable interface because it is implemented in the base class.
public   class  MyResourceWrapper: BaseResource
{
   
//  A managed resource that you add in this derived class.
    private  ManagedResource addedManaged;
   
//  A native unmanaged resource that you add in this derived class.
    private  NativeResource addedNative;
   
private   bool  disposed  =   false ;

  
//  Constructor for this object.
    public  MyResourceWrapper()
   {
      
//  Insert appropriate constructor code here.
   }

   
protected   override   void  Dispose( bool  disposing)
   {
      
if ( ! this .disposed)
      {
         
try
         {
            
if (disposing)
            {
               
//  Release the managed resources you added in
               
//  this derived class here.
               addedManaged.Dispose();         
            }
            
//  Release the native unmanaged resources you added
            
//  in this derived class here.
            CloseHandle(addedNative);
            
this .disposed  =   true ;
         }
         
finally
         {
            
//  Call Dispose on your base class.
             base .Dispose(disposing);
         }
      }
   }
}

//  This derived class does not have a Finalize method
//  or a Dispose method without parameters because it inherits 
//  them from the base class.


有一个热传的对象复活(resurrection)的例子
public   class  Resurrection
{
    
public   int  Data;

    
public  Resurrection( int  data)
    {
        Data 
=  data;
    }

    
~ Resurrection()
    {
        Main.Instance 
=   this ;
    }
}

public   class  Main
{
    
public   static  Resurrection Instance;

    
public   static   void  Main()
    {
        Instance 
=   new  Resurrection( 1 );
        Instance 
=   null ;
        GC.Collect();
        GC.WaitForPendingFinalizers();

        
//  看到了吗,在这里“复活”了。 
        Console.WriteLine(Instance.Data);
        Instance 
=   null ;
        GC.Collect();
        Console.ReadLine();
    }
}

还有一个弱引用的例子,弱引用的对象在回收以前还是可以被重复使用的。
public   class  Fat
{
    
public   int  Data;

    
public  Fat( int  data)
    {
        Data 
=  data;
    }
}

public   class  MainClass
{
    
public   static   void  Main()
    {
        Fat oFat 
=   new  Fat( 1 );
        WeakReference oFatRef 
=   new  WeakReference(oFat);

        
//  从这里开始,Fat对象可以被回收了。
        oFat  =   null ;
        
if  (oFatRef.IsAlive)
        {
            Console.WriteLine(((Fat) oFatRef.Target).Data);
        }
        
        GC.Collect();
        Console.WriteLine(oFatRef.IsAlive); 
//  False 
        Console.ReadLine();
    }
}


参考:
http://msdn2.microsoft.com/zh-cn/library/fs2xkftw(VS.80).aspx
http://blog.youkuaiyun.com/sykpboy/archive/2005/04/11/342971.aspx

转载于:https://www.cnblogs.com/forck/archive/2008/04/16/1156343.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值