返回信息流C#中dispose的标准模式是写两个dispose方法,一个是公有的不带参数的dispose()方法,一个是私有的带布尔参数的dispose(bool disposing)方法.一个例子如下:
public class DisposeTest:IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// 释放托管资源
}
// 释放非托管资源
}
disposed = true;
}
~DisposeTest()
{
Dispose(false);
}
}
我的疑问在于Dispose(true)和Dispose(false)的区别上。我查阅过很多资料,所有的资料上都如下所述“当用户显示调用Dispose()方法时,要清理托管资源和非托管资源,并且调用GC.SuppressFinalize方法阻止垃圾收集器再次调用Finalise方法;当用户没有调用Dispose()方法,而是由垃圾收集器调用Finalize方法时,应该只释放非托管资源,而不应释放托管资源。因为假若在Finalize方法中引用另一个托管对象时,我们无法确定此时该托管对象的状态如何(是否已被回收)。”我非常不明白的是为什么Finalize方法中不能含有托管类型的引用,按照他们说的,“无法确定此时该托管对象的状态如何”,那么对于其他方法而言,它们里面为什么可以含有其他托管类型的引用???
这是一条镜像帖。来源:北邮人论坛 / dot-net / #3728同步于 2012/5/19
该镜像源已超过 30 天没有更新,可能在源站已被删除。
dotNET机器人发帖
[问题]C#中dispose方法
liuke20008
2012/5/19镜像同步5 回复
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
你的这段话,可以理解为,除非为了手动释放"非托管资源",否则没必要自己写释放资源的方法,由GC自己判断就行了。
由于GC自己释放托管资源的时候,会调用Finalize。
~DisposeTest()
{ }
C#的这个所谓析构函数,就是Finalized。
你如果在这里也释放托管资源,相当于帮GC做了一点事情,是没必要的。
并且每个对象在某个方法里面被引用,就会导致它的生命期延长。
可以在任何方法调用托管对象,得看有没必要。
手动释放托管对象是没必要的。
如果要释放托管资源,调用GC.Collect()触发垃圾收集就行了。
【 在 ahomer 的大作中提到: 】
: 你的这段话,可以理解为,除非为了手动释放"非托管资源",否则没必要自己写释放资源的方法,由GC自己判断就行了。
: 由于GC自己释放托管资源的时候,会调用Finalize。
: ~DisposeTest()
: ...................
这是摘自《Csharp高级编程(第6版)》里的一段话,红线标注的是我疑问的地方,它的意思不就是在析构函数里不应该访问托管对象么?
【 在 ahomer 的大作中提到: 】
: 你的这段话,可以理解为,除非为了手动释放"非托管资源",否则没必要自己写释放资源的方法,由GC自己判断就行了。
: 由于GC自己释放托管资源的时候,会调用Finalize。
: ~DisposeTest()
: ...................
囧,不会发图。还是把原话打上去吧。
“传递给Dispose(bool)的参数表示Dispose(bool)是由析构函数调用还是由IDispose.Dispose()调用——Dispose(bool)不应从代码的其他地方调用,其原因是:
1.如果客户调用IDispose.Dispose(),该客户就指定应清理所有与该对象相关的资源,包括托管资源和非托管的资源;
2.如果调用了析构函数,原则上所有的资源仍需要清理。但是在这种情况下,析构函数必须由垃圾收集器调用,而且不应访问其他托管的对象,因为我们不再能确定它们的状态了。在这种情况下,最好清理已知的未托管资源,希望引用的托管对象还有析构函数,执行自己的清理过程。
”(打字好累~)
在finilize的时候,是gc在工作,说明已经开始gc了,其他工作都被hold住。而gc回收的顺序是不定的,在finilize里面访问另外一个托管对象,这个对象可能已经被gc掉了