有很多关于.Net的书籍和文章都描述了如何实现IDisposable接口,但是几乎每一篇实现的都不完全一样,这里将几个主要的实现进行合并,试图找出能够适应绝大多数条件的实现方法。
实现代码
1
namespace Disposable
2

{
3
public class ResourceBase:IDisposable
4
{
5
private bool disposed = false;
6
7
~ResourceBase()
8
{
9
Dispose(false);
10
}
11
12
protected virtual void Dispose(bool disposing)
13
{
14
if (disposed)
15
return;
16
//多线程环境
17
lock (this)
18
{
19
if (disposing)
20
{
21
//release managed resource
22
}
23
//release unmanaged resource;
24
disposed = true;
25
}
26
}
27
public void Close()
28
{
29
Dispose();
30
}
31
32
IDisposable Members#region IDisposable Members
33
34
public void Dispose()
35
{
36
Dispose(true);
37
GC.SuppressFinalize(this);
38
}
39
40
#endregion
41
}
42
public class Resource:ResourceBase
43
{
44
private bool disposed = false;
45
protected override void Dispose(bool disposing)
46
{
47
if (disposed)
48
return;
49
//多线程环境
50
lock (this)
51
{
52
try
53
{
54
if (disposing)
55
{
56
//release managed resource
57
}
58
//release unmanaged resource
59
60
}
61
finally
62
{
63
base.Dispose(disposing);
64
disposed = true;
65
}
66
67
}
68
69
}
70
}
71
}

2



3

4



5

6

7

8



9

10

11

12

13



14

15

16

17

18



19

20



21

22

23

24

25

26

27

28



29

30

31

32


33

34

35



36

37

38

39

40

41

42

43



44

45

46



47

48

49

50

51



52

53



54

55



56

57

58

59

60

61

62



63

64

65

66

67

68

69

70

71

分析
Dispose()方法用于显式的释放资源,可以在代码中直接调用,或者使用using语句间接调用。GC.SuppressFinalize告诉GC在垃圾回收时,不需要调用析构函数,可以提高垃圾回收的效率。
Close()方法与Dispose()作用相同,只是为了适应某些有Open方法的类,Open/Close相互对应比较符合一般习惯。
析构函数用于在垃圾回收的时候释放资源。如果用户没有/忘记在使用之后释放资源,CLR会在垃圾回收的时候调用此函数。虽然资源较晚被释放,但总是好于不释放。
Dispose(bool)是真正释放资源的地方,参数disposing表明是用户主动释放资源还是在垃圾回收时释放。当用户主动释放资源时,由于此对象的成员中,某些托管资源持有非托管资源,因此需要释放这些托管资源,如果这些托管资源实现了IDisposable,调用Dispose()即可。在垃圾回收时,由于无法确定这些托管资源是否已经被回收了,因此不要试图释放托管资源,GC会释放这些资源的。如果多次调用Dispose(bool)会有副作用,则需要添加disposed变量来判断是否已经释放了资源。如果对象可能会在多线程环境中使用,需要加锁防止同步问题。
最后,如果该类有派生类的话,要在派生类中override父类的Dispose(bool)方法,并在释放资源后调用父类的Dispose(bool),以正确释放父类的资源。