使用一个实现IDispose接口的对象,怎样才是最佳实践?

梁苏彬 2009-06-30 09:57:20
有些类比如Font是实现了IDispose接口的,我不太清楚应该怎么使用这种对象,应该--
1. 每次使用对象时都用using{}
2. 每次用完都显式调用该对象Dispose()方法
3. 不管(会不会自动回收一切资源?)

请指教。
...全文
594 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
fengjian_428 2009-07-06
  • 打赏
  • 举报
回复
DataView,DataSet不需要dispose 这个我可以确定 当然用了也没坏处
梁苏彬 2009-07-06
  • 打赏
  • 举报
回复
但是我在查阅DataView,DataSet类的帮助时,又没有明确提出必须要显式调用Dispose()方法。

我感觉微软自己的代码在实施Dispose模式时也是有些混乱的。目前我为了安全,还是在所有使用带dispose方法的对象的地方,都调用其dispose
梁苏彬 2009-07-06
  • 打赏
  • 举报
回复
在MSDN上看到两个需要显式dispose的例子。我的理解,这两个例子里如果不调用Dispose是有问题的。
第一个是Timer类, MSDN上说
"If you are making a lot of Timers that only fire once, take care to call Dispose() on them after you are finished. If you don't, garbage collection will

never clean them up, even after their job has finished.
You can safely dispose of a Timer object inside the Elapsed event handler if you need to."
来源http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

第二个是Font Class,虽然没有说必须要调用Dispose方法,但Font类的例子里使用完是调用了Dispose的。同样的有Brush, Pen.
来源http://msdn.microsoft.com/en-us/library/5af3hke9.aspx
happyboyxq 2009-07-06
  • 打赏
  • 举报
回复
如果你想尽可能少的占用资源,那你每次使用完就自己添加dispose方法,也可以不管,VS有自己的回收机制,不过可能会长时间占用内存。
梁苏彬 2009-07-06
  • 打赏
  • 举报
回复
关于DataSet要不要释放,在网上搜了一下,也是众说纷纭,很多人都说没释放也没事,也有人建议要释放,下面是搜到的一个。Dispose这样的东西不释放确实不容易看出问题。
-------------------------------------------------------------------------------
在AccessImport项目中,所使用的DataSet都是由SqlDataAdapter生成的(不是动态)。数据表发现很多重复数据,追了很久才查到原因:DataSet在从新写入数据时没有清空,如果此时Fill的话,只是在以前的数据后面追加数据,如果该表没有主键,在insert的时候就会再次写入以前的数据。所以建议在使用sqlDataAdapter.Fill(DataSet)之前,先把DataSet清空一下:DataSet.clear()。在使用完之后,最好把DataSet的资源释放掉:DataSet.dispose()。
http://www.cnblogs.com/dusy/archive/2007/08/24/868068.html
fengjian_428 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 fengjian_428 的回复:]
之所以在dispose的时候重写析构函数是为了防止你忘记用using又没有显示调用的时候仍然能够释放托管资源。
[/Quote]
是非托管资源 写错了
fengjian_428 2009-06-30
  • 打赏
  • 举报
回复
对象在垃圾回收的时候都会调用析构函数,这里的析构函数只能释放托管资源
释放非托管资源用dispose

之所以在dispose的时候重写析构函数是为了防止你忘记用using又没有显示调用的时候仍然能够释放托管资源。
这样应该清楚了吧
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hbxtlhx 的回复:]
那么我使用C#的File, Font, Brush, Dataset...这些类的对象后是否必须用1或2的方式?
--------------------
是的。不用是不正确的。
[/Quote]
我有个疑问。如果我的类实现了IDisposable,则使用我的类的地方需要调用我的Dispose()方法。那么我能不能把Dispose()写在析构函数里呢?这样使用者即使没有调用Dispose(),也能保证最终会被调用。
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fengjian_428 的回复:]
析构跟dispose没关系的
析构释放托管资源 是自动调用

非托管资源析构函数释放不了 只有自己在类里实现dispose去释放 你写成别的名字的方法释放资源也是一样的,只是不能再using的时候自动调用而已
[/Quote]
好像并不是这样,析构函数可以释放非托管资源。微软的Dispose模式里是这样写的。下面是我根据大家的回复写的代码,有错误请指出。

public void Dispose()//使用此类的地方需要显示调用这个方法或using
{
Dispose(true); //既释放托管资源,也释放非托管资源
Gc.SuppressFinalize(this); //告诉GC回收对象时不必调用~ClassName()了,因为Dispose(true)已经把事情做完了
}
~ClassName() //这个方法由GC回收对象时自动调用
{
Dispose(false); //释放非托管资源
}
Protected virtual void Dispose(bool disposing)
{
if (disposing)
{//释放托管资源
managedResource.Dispose();
}
//释放非托管资源
}

fengjian_428 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lsbbox 的回复:]
引用 11 楼 vrhero 的回复:
只有两个原则...

1.凡是使用了GC无法回收的非托管资源的,必须实现IDispose接口释放这些资源...对使用者来说使用完毕必须调用Dispose方法...

2.没有使用非托管资源的...无需IDispose接口...

ps:IDispose接口和析构函数不是一回事儿...在.NET中你可以忽略析构函数当它不存在,老老实实用Dispose方法...

您说的是一种方法,不过好像微软的Dispose模式有些不同,非托管资源既在Dispose(false)里释放,也在析构函数里释放,这样保证非托管资源最后一定被释放。只是靠析构函数释放非托管资源,释放时机不可控制(我的理解)
[/Quote]
乱讲 析构函数释放非托管资源是不可能的
fengjian_428 2009-06-30
  • 打赏
  • 举报
回复
析构跟dispose没关系的
析构释放托管资源 是自动调用

非托管资源析构函数释放不了 只有自己在类里实现dispose去释放 你写成别的名字的方法释放资源也是一样的,只是不能再using的时候自动调用而已
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 vrhero 的回复:]
只有两个原则...

1.凡是使用了GC无法回收的非托管资源的,必须实现IDispose接口释放这些资源...对使用者来说使用完毕必须调用Dispose方法...

2.没有使用非托管资源的...无需IDispose接口...

ps:IDispose接口和析构函数不是一回事儿...在.NET中你可以忽略析构函数当它不存在,老老实实用Dispose方法...
[/Quote]
您说的是一种方法,不过好像微软的Dispose模式有些不同,非托管资源既在Dispose(false)里释放,也在析构函数里释放,这样保证非托管资源最后一定被释放。只是靠析构函数释放非托管资源,释放时机不可控制(我的理解)
vrhero 2009-06-30
  • 打赏
  • 举报
回复
只有两个原则...

1.凡是使用了GC无法回收的非托管资源的,必须实现IDispose接口释放这些资源...对使用者来说使用完毕必须调用Dispose方法...

2.没有使用非托管资源的...无需IDispose接口...

ps:IDispose接口和析构函数不是一回事儿...在.NET中你可以忽略析构函数当它不存在,老老实实用Dispose方法...
北京的雾霾天 2009-06-30
  • 打赏
  • 举报
回复
那么我使用C#的File, Font, Brush, Dataset...这些类的对象后是否必须用1或2的方式?
--------------------
是的。不用是不正确的。
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 showjancn 的回复:]
简单的来说是为了实现析构.
即在析构函数中调用 Dispose(true);
来释放非托管代码和资源。

可查阅MSDN中的“析构函数”。

一个简单的例子。
有一个类的实例,在构造函数或其它函数中打开了的一个串口。为了防止此实例消亡后(如果未关闭串口)。串口还可供其它实例可用。那么最好在Dispose中判断一下,如果串口被占用,则关闭它。
[/Quote]
好像在~ClassName()析构函数里都是调用Dispose(false)吧?
showjancn 2009-06-30
  • 打赏
  • 举报
回复
简单的来说是为了实现析构.
即在析构函数中调用 Dispose(true);
来释放非托管代码和资源。

可查阅MSDN中的“析构函数”。

一个简单的例子。
有一个类的实例,在构造函数或其它函数中打开了的一个串口。为了防止此实例消亡后(如果未关闭串口)。串口还可供其它实例可用。那么最好在Dispose中判断一下,如果串口被占用,则关闭它。
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hbxtlhx 的回复:]
如果使用Using则不必再调用Dispose方法。
如果不使用Using则必需调用Dispose方法。

你可以不用这两种方式,程序也不会有很明显的问题,但是这些对象的非托管资源不会被释放。
[/Quote]

那么我使用C#的File, Font, Brush, Dataset...这些类的对象后是否必须用1或2的方式?
北京的雾霾天 2009-06-30
  • 打赏
  • 举报
回复
如果使用Using则不必再调用Dispose方法。
如果不使用Using则必需调用Dispose方法。

你可以不用这两种方式,程序也不会有很明显的问题,但是这些对象的非托管资源不会被释放。
rollng 2009-06-30
  • 打赏
  • 举报
回复
gc机制,建议你想了解清楚的话网上搜一下。
梁苏彬 2009-06-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fengjian_428 的回复:]
1,用using{}的时候会在using结束的时候自动调用Dispose方法
2.如果用了using就不用再显示调用了
3.dispose方法是在继承了接口的类中自己实现的,具体看是怎么实现的了
[/Quote]

谢谢2楼!对于3,很多系统类都有dispose,比如Font, Dataset。在使用这些对象时怎么做才是合适的?
加载更多回复(4)

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧