C# IDisposable的理解

C#里可以嵌入非托管代码,这就涉及到了这些代码资源的释放。以前总是看到别人的代码里那么写,也没有好好想想为什么,今天看了书,总结一下。

资源释放分为两种:

  1. 托管的
  2. 非托管的

两者的释放方式不一致:

  1. 没有非托管资源的,GC在运行时,会自动回收和释放;
  2. 含有非托管资源的,必须提供一个析构器,他们也会在内存里停留的时间会更长,最终被加入一个叫做finalization queue的结构,然后由GC在另一个线程释放;

实现IDispose接口是一种标准的释放资源的方式,正确使用会减少很多的bug和因为资源释放而引起的问题。正如上面所说,包含了非托管资源的代码,是必须提供一个析构器的。这样做的目的,是为了保证类的使用者,即使没有显式地调用Dispose方法,也可以正确地释放资源。

生产环境中的代码里,会有很多的继承,因此为了保证子类在调用时能够正确地执行父类的资源释放,在标准模式中,将真正的资源释放方法Dispose方法,抽象为一个virtual的方法,由子类去override,并在其中调用base的Dispose方法。

释放资源的Dispose方法,应该完成以下几件事(引用Effective C#)

  1. 释放所有的非托管资源;
  2. 释放所有的托管资源;
  3. 设定一个标志,标志资源是否已经销毁;对于销毁的对象,仍旧调用,则应抛异常;
  4. 跳过终结操作,调用GC.SuppressFinalize(this)方法。

以上,文字内容结束,基本的代码如下:

 1 using System;
 2 using System.Diagnostics;
 3 
 4 namespace Learn
 5 {
 6     class Program
 7     {
 8         private static int Cnt = 100000;
 9 
10         static void Main(string[] args)
11         {
12             Stopwatch sw = new Stopwatch();
13             sw.Start();
14             for (int i = 0; i < Cnt; i++)
15             {
16                 IDisposeDerived de = new IDisposeDerived();
17             }
18             sw.Stop();
19             Console.WriteLine("total time is: " + sw.ElapsedMilliseconds);
20             Console.ReadLine();
21         }
22     }
23 
24     internal class IDisposeBase : IDisposable
25     {
26         // never add this unless unmanaged resources exist
27         // cauz this will add extra burdon and make negative influence on performance
28         //~IDisposeBase()
29         //{
30         //    Dispose(false);
31         //}
32 
33         private bool AlreadyDisposed = false;
34 
35         public void Dispose()
36         {
37             Dispose(true);
38             GC.SuppressFinalize(this);
39         }
40 
41         protected virtual void Dispose(bool shouldDisposeManagedReources)
42         {
43             if (AlreadyDisposed)
44                 return;
45             if (shouldDisposeManagedReources)
46             {
47                 // dispose the managed resources
48                 // release the events
49                 // etc.
50             }
51             // dispose the unmanaged resources
52 
53             // set the flag
54             AlreadyDisposed = true;
55         }
56 
57         public void MethodForPublic()
58         {
59             if (AlreadyDisposed)
60                 throw new Exception("object has been disposed!");
61             // do the normal things
62         }
63     }
64 
65     internal class IDisposeDerived : IDisposeBase
66     {
67         //~IDisposeDerived()
68         //{
69         //    Dispose(false);
70         //}
71 
72         private bool AlreadyDisposed = false;
73 
74         protected override void Dispose(bool shouldDisposeManagedReources)
75         {
76             if (AlreadyDisposed)
77                 return;
78             if (shouldDisposeManagedReources)
79             {
80                 // dispose managed resources
81             }
82             // dispose unmanaged resources
83 
84             // call the base's dispose method
85             base.Dispose(shouldDisposeManagedReources);
86 
87             // set the flag
88             AlreadyDisposed = true;
89         }
90     }
91 }

代码里增加了包含析构器的实现,可以对比一下,性能差异十分明显。

无析构器的实现结果:

有析构器的实现结果:

原文地址:https://www.cnblogs.com/warnet/p/5084504.html