首先,Dispose和Close基本上应该是同样的。Close是为了那些不熟悉Dispose的开发者设计的。由于基本上全部的开发者都知道Close是干嘛的(特别是对于那些有C++背景的开发者)
可是当咱们写代码时候,若是要实现Close和Dispose的时候,要注意Close和Dispose的设计模式。.net的一些class只提供Close,并且派生自IDisposable,而且隐藏了Dispose方法。是否是以为很不明白了?
对这些class来讲,关键在于它们显式的(explicitly)实现了IDisposable。对于隐式实现来讲,你只须要调用"new A().Dispose()",可是对于显式实现来讲,Dispose不会是这个class的成员函数。惟一的调用方式是你先要cast到 IDisposable才行。(“new A().Dispose()”编译不过,可是“((IDisposable)new A()).Dispose()”能够编译过)。因此这样就符合了设计的要求:提供Close(),隐藏Dispose(),而且实现了 IDisposable接口。
在.net的framework里,Close()被设计成public的,而且在Close()里面call被隐藏的Dispose(); Dispose()去call另外一个virtual的Dispose(bool)函数。因此若是你从这个class继承,你就必须实现Dispose (bool)方法。
调用者call Close()的时候就会call到你重载的那个Dispose(bool)方法去释放资源。
请参考
http://blogs.msdn.com/brada/archive/2003/07/06/50127.aspx
注意事项:
1,Close()不该该被定义成virtual。对于这个design pattern,Close()只是用来call那个隐藏的Dispose(),用户不该该改变Close的behavior。对于这个问题, System.IO.Stream也有设计问题。之因此有问题是为了知足向后兼容的需求。See
http://msdn2.microsoft.com/en-us/library/ms227422.aspx. 文档里面提到虽然Close()是virtual的,可是不该该被override。
演示代码以下:
1
using
System;
2
3
namespace
ConsoleApplication
4
{
5
abstract
class
MyStream : IDisposable
6
{
7
public
MyStream()
8
{
9
m_unmanagedResource
=
Marshal.AllocCoTaskMem(
100
);
10
m_bitmap
=
new
Bitmap(
50
,
50
);
11
}
12
13
#region
IDisposable Members
14
void
IDisposable.Dispose()
15
{
16
Dispose(
true
);
17
GC.SuppressFinalize(
this
);
18
}
19
20
protected
virtual
void
Dispose(
bool
isDisposing)
21
{
22
if
(
!
m_disposed)
23
{
24
if
(isDisposing)
25
{
26
m_bitmap.Dispose();
27
}
28
Marshal.FreeCoTaskMem(m_unmanagedResource);
29
m_disposed
=
true
;
30
}
31
}
32
33
public
void
Close()
34
{
35
((IDisposable)
this
).Dispose();
36
}
37
38
~
MyStream()
39
{
40
Dispose(
false
);
41
}
42
43
private
IntPtr m_unmanagedResource;
//
Unmanaged resource
44
private
Bitmap m_bitmap;
//
IDisposable managed resources
45
private
bool
m_disposed;
46
47
#endregion
48
}
49
50
class
MyDerivedStream : MyStream
51
{
52
public
MyDerivedStream()
53
{
54
m_anotherMemory
=
Marshal.AllocCoTaskMem(
20
);
55
m_anotherImage
=
new
Bitmap(
24
,
24
);
56
}
57
58
protected
override
void
Dispose(
bool
isDisposing)
59
{
60
if
(
!
m_disposed)
61
{
62
if
(isDisposing)
63
{
64
m_anotherImage.Dispose();
65
}
66
67
Marshal.FreeCoTaskMem(m_anotherMemory);
68
base
.Dispose(isDisposing);
69
m_disposed
=
true
;
70
}
71
}
72
73
public
static
void
Main(
string
[] args)
74
{
75
MyStream aStream
=
new
MyDerivedStream();
76
77
aStream.Close();
//
Allowed
78
//
aStream.Dispose();
//
Cannot compile
79
80
((IDisposable)aStream).Dispose();
//
Allowed
81
82
//
83
//
This one works as well, because newStream calls the explicit implemented
84
//
IDisposable.Dispose method
85
//
86
using
(MyStream newStream
=
new
MyDerivedStream())
87
{
88
//
89
//
Do something
90
//
91
}
92
}
93
94
private
IntPtr m_anotherMemory;
95
private
Bitmap m_anotherImage;
96
private
bool
m_disposed;
97
}
98
}
99