现在的位置: 首页 > 综合 > 正文

C# IDisposable 接口

2013年10月04日 ⁄ 综合 ⁄ 共 5982字 ⁄ 字号 评论关闭

 

 

析构函数 ~MyResource()  仅用来释放非托管资源(重用Dispose方法实现)

当不显示调用Dispose时,CLR释放托管内存前,调用析构函数清理非托管资源

 

显示调用Dispose:

Dispose()释放所有资源(托管与非托管)

 

 

An Insight into the Dispose and Finalize Methods
The .NET garbage collector manages the memory of managed objects (native .NET objects) but it does not manage, nor is it directly able to clean up unmanaged resources. Managed resources are those that are cleaned up implicitly by the garbage collector. You do not have to write code to release such resources explicitly. In contrast, you must clean up unmanaged resources (file handles, database collections, etc.) explicitly in your code.

There are situations when you might need to allocate memory for unmanaged resources from managed code. As an example, suppose you have to open a database connection from within a class. The database connection instance is an unmanaged resource encapsulated within this class and should be released as soon as you are done with it. In such cases, you'll need to free the memory occupied by the unmanaged resources explicitly, because the GC doesn't free them implicitly.

Briefly, the GC works as shown below:

  • It searches for managed objects that are referenced in managed code.
  • It then attempts to finalize those objects that are not referenced in the code.
  • Lastly, it frees the unreferenced objects and reclaims the memory occupied by them.

The GC maintains lists of managed objects arranged in "generations." A generation is a measure of the relative lifetime of the objects in memory. The generation number indicates to which generation an object belongs. Recently created objects are stored in lower generations compared to those created earlier in the application's life cycle. Longer-lived objects get promoted to higher generations. Because applications tend to create many short-lived objects compared to relatively few long-lived objects, the GC runs much more frequently to clean up objects in the lower generations than in the higher ones.

 

The Dispose Method—Explicit Resource Cleanup
Unlike Finalize, developers should call Dispose explicitly to free unmanaged resources. In fact, you should call the Dispose method explicitly on any object that implements it to free any unmanaged resources for which the object may be holding references. The Dispose method generally doesn't free managed memory—typically, it's used for early reclamation of only the unmanaged resources to which a class is holding references. In other words, this method can release the unmanaged resources in a deterministic fashion.

However, Dispose doesn't remove the object itself from memory. The object will be removed when the garbage collector finds it convenient. It should be noted that the developer implementing the Dispose method must call GC.SuppressFinalize(this) to prevent the finalizer from running.

Note that an object should implement IDisposable and the Dispose method not only when it must explicitly free unmanaged resources, but also when it instantiates managed classes which in turn use such unmanaged resources. Implementing IDisposable is a good choice when you want your code, not the GC, to decide when to clean up resources. Further, note that the Dispose method should not be called concurrently from two or more different threads as it might lead to unpredictable results if other threads still have access to unmanaged resources belonging to the instance.

The IDisposable interface consists of only one Dispose method with no arguments.

   public interface IDisposable
   {
      void Dispose();
   }

The following code illustrates how to implement the Dispose method on a class that implements the IDisposable interface:

   class Test : IDisposable
   {
     private bool isDisposed = false;
   
     ~Test()
     {
       Dispose(false);
     }
   
     protected void Dispose(bool disposing)
     {
       if (disposing)
       {
         // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class
   
       isDisposed = true;
     }
   
     public void Dispose()
     {
       Dispose(true);
       GC.SuppressFinalize(this);
     }
   }
   
   

In the preceding code, when the Boolean variable disposed equals true, the object can free both managed and unmanaged resources; but if the value equals false, the call has been initiated from within the finalizer (~Test) in which case the object should release only the unmanaged resources that the instance has reference to.

抱歉!评论已关闭.