在天空飞翔
博客园
社区
首页
新随笔
联系
管理
订阅
随笔- 28 文章- 0 评论- 83
2007年12月28日
正确实现 IDisposable 接口
前言: 之前在M$的一本工具书上看过该节内容,但慢慢地就忘记了, 在实际项目遇到类似的问题又要 google, 汗下, 于是写此篇blog作备忘录 。
虽然 .net 有垃圾回收机制(GC), 可自动进行大部分的资源清理工作,但开发人员仍旧应该养成良好的通过手动调用资源清理方法来进行资源回收的习惯, 让对象实现
IDisposable
接口正是 M$ 所推荐的, 该接口的原型为:
//
Summary:
//
Defines a method to release allocated unmanaged resources.
[ComVisible(
true
)]
public
interface
IDisposable
{
//
Summary:
//
Performs application-defined tasks associated with freeing, releasing, or
//
resetting unmanaged resources.
void
Dispose();
}
注:.net 内部也有传说中的”析构函数“,就是
Finalize()
, 该函数由GC自动调用。
实现 Dispose 需要注意的是
1. 如果资源已手动释放过了,就应该通知GC,不要再对该对象执行 Finalize 操作
2. 确保重复执行 Dispose 时不会出错
根据以上规则, 简单的定义一个类 classSample
public
class
classSample : IDisposable
{
/**/
///
<summary>
///
该对象是否已被销毁过
///
</summary>
private
bool
disposed;
/**/
///
<summary>
///
这就是传说中的 Finalize函数,是不是和C++的析构函数很像?
///
</summary>
~
classSample()
{
Console.WriteLine(
"
对象被销毁
"
);
Dispose(
false
);
}
public
void
Dispose()
{
Console.WriteLine(
"
手动销毁对象
"
);
Dispose(
true
);
//
通知GC, 偶已经被销毁过了,可以不用再管偶了。。。
GC.SuppressFinalize(
this
);
}
/**/
///
<summary>
///
Dispose
///
</summary>
///
<param name="disposing">
是否由程序直接调用
</param>
protected
void
Dispose(
bool
disposing)
{
if
(
!
disposed)
{
if
(disposing)
{
//
该函数为手动调用,此处可进行托管资源的清理
//
比如此类中有一个类型为 DataSet 的变量 dsData
//
此处可调用该对象的 Dispose 方法来清理托管资源
dsData.Dispose();
}
//
进行非托管资源的清理
//
非托管的资源主要为一些用 API 打开的文件句柄,设备场景句柄等
//
该类资源 GC 是无法管理的,只能依靠程序员自已释放
//
不同的资源, 释放方法不一样
//例如:
//
释放文件句柄 (定义API的代码略。)
CloseHandle(handle);
//
释放GDI 中的设备场景 (定义API的代码略。)
ReleaseDC(hdc);
}
disposed
=
true
;
}
}
注意
protected
void
Dispose(
bool
disposing) 函数, 清理托管资源和非托管资源的代码位置不要写反了,否则当一个托管对象已经被GC回收后,再去调用它的Dispose 方法, 系统会触发一个 ObjectDisposedException 异常
到这里 ,一个简单的实现
IDisposable 的类已经写好了, 再写段测试代码看看
private
void
button1_Click(
object
sender, EventArgs e)
{
classSample cls
=
new
classSample();
}
点击按钮, 再关闭程序, 可看到 output 窗口中显示
对象被销毁
说明 Finalize 函数被执行了
换一个
private
void
button1_Click(
object
sender, EventArgs e)
{
classSample cls
=
new
classSample();
cls.Dispose();
}
再看 output 窗口中,只显示了”手动销毁对象“, 说明在手动执行Dispose 后,已正确通知GC,不再执行
Finalize函数。
小技巧: 可使用 using 关键字来定义对象的生存期,
超出 using范围 后,如果对象实现了
IDisposable接口, 系统会自动调用其 Dispose 方法, 是不是很方便。
using
(classSample cls
=
new
classSample())
{
}
看,我并没有调用 Dispose 方法, output 窗口中还是会显示 ”手动销毁对象“.
posted @
2007-12-28 16:08
在天空飞翔 阅读(2380) |
评论 (12)
|
编辑
<
2007年12月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
1
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
1
2
3
4
5
与我联系
发短消息
搜索
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
我的新闻
最新评论
我的标签
留言簿
给我留言
查看留言
我参加的小组
创业交流
设计模式
WinForms
我的标签
mp3(1)
分类(1)
c#(1)
多任务(1)
随笔分类
C#(17)
(rss)
链接(1)
(rss)
休闲(9)
(rss)
随笔档案
2008年10月 (1)
2008年9月 (2)
2008年8月 (2)
2008年7月 (2)
2008年5月 (2)
2008年4月 (1)
2008年3月 (1)
2008年1月 (3)
2007年12月 (6)
2007年8月 (1)
2007年7月 (1)
2007年6月 (3)
2007年5月 (3)
最新评论
1. re: [源码]用c#创建支持多语言的应用程序
还有个问题就是我们设置的是第一个页面,假如有几个页面的话,那可怎么办哦 (sky431)
2. re: 扩展 DataGridView 的功能(二)
照着编怎么运行的效果怎么不一样,望发一份可以运行的代码到小弟的邮箱。谢谢!
(email :ybqhyyhl@163.com) (hale)
3. re:扩展 DataGridView 的功能(二)
很好,很强大 (短笛大魔王)
4. re: 扩展 DataGridView 的功能(二)
还是支持一下楼主。因为俺还没有见过。 (Small0426)
5. re: 扩展 DataGridView 的功能(二)
这个效果早就有源码公布了.
lz , 你是浪费大家表情.
摘抄他人的,也注明转 (gavin.chen)
阅读排行榜
1. 正确实现 IDisposable 接口(2380)
2. 支持函数,变量的算术表达式计算(三、加入函数)(2232)
3. 扩展 DataGridView 的功能(一)(2231)
4. 支持函数,变量的算术表达式计算(二、中缀转后缀)(1814)
5. 扩展 DataGridView 的功能(二)(1659)
评论排行榜
1. 支持函数,变量的算术表达式计算(一、计算后缀表达式)(15)
2. 扩展 DataGridView 的功能(一)(12)
3. 正确实现 IDisposable 接口(12)
4. 支持函数,变量的算术表达式计算(二、中缀转后缀)(11)
5. 支持函数,变量的算术表达式计算(三、加入函数)(6)