首先,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