这是MSDN的 接口说明
http://msdn.microsoft.com/zh-cn/library/system.idisposable.aspx
可以看到 IDisposable 接口只是针对非托管资源释放,上面链接中的例子有一段如下,
protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if(!this.disposed) { //如果等于true处理,处理所有托管和非托管资源。 if(disposing) { //处理托管资源。 component.Dispose(); } // Call the appropriate methods to clean up // unmanaged resources here. // If disposing is false, // only the following code is executed. CloseHandle(handle); handle = IntPtr.Zero; // Note disposing has been done. disposed = true; } }
中文解释那个地方有疑问
1. component对象是托管对象,component调用Dispose()之后也只是释放component里面的非托管资源,为什么注释是 处理托管资源呢?
2. 托管资源,能不能手动手动释放,显示释放?能的话,怎么释放? 不要说GC.Collect
希望各位园友 指点一下
问题1:你所说的都是对的。这里component是一个“包含了非托管资源的托管资源”,它本身是托管资源,只不过包含了非托管资源。为此我特地去看了一下你发的链接的英文版,发现这里其实是个英文的理解问题。把注释换成这样应该就能理解了:
//如果等于true,则处理所有“包含了非托管资源的托管资源”和“本身的纯非托管资源” if(disposing) { //处理包含非托管资源的托管资源 component.Dispose(); } //以下是处理非托管资源
问题2:GC会把“没有用的”托管资源统一回收处理。这里你说的“释放”一词有不明确的含义。你可以通过把变量指向null,使堆上的某个对象不再有任何引用指向它,从而它被GC认为是“没有用的”而被回收掉。但是严格来讲并不是“a = null;"这句”释放”了托管资源,它只是不再指向托管资源,虽然这样做的后果是托管资源被认为是垃圾而被回收了。
1. 你的意思是说 IDisposable的Dispose方法只能释放非托管资源吗?
那一个没有包含非托管资源的类实现了IDisposable 接口,有什么影响吗,如性能...?
2. 释放托管资源的意思是说释放托管内存,把它占有的内存释放掉,不能显示释放吗?只能等GC来释放?
@Qlin: 1. 并非“只能”,而是“只需要”,你在Dispose方法里把一些内部成员设置成null,也是可以的,但是还是等待GC回收,并没有立即回收。2.不能直接释放内存,只能通过GC。
@水牛刀刀:
飞常谢谢
文章很好,我的问题里面说的 也不是很清楚。
大侠能直接说说你的理解 好吗?
1. IDisposable 只能释放所有的非托管资源,而不包含托管资源,是不是?
2. 托管资源只能由Gc定期来释放吗? 能不能手动释放,跟调用Dispose方法类似的,有木有?
看你总结起来就两个疑惑:
1,Dispose释放什么资源?
都可以。就看你如何实现你的代码逻辑。非托管资源的释放一般都是通过调用native的api去释放的,而托管的一般都是让堆内存不再被引用就可以了。这里让你困惑的可能是为什么component还要调用dispose去释放,原因是component里面可能需要释放的非托管资源,就看component的dispose怎么实现了,因为它自己最清楚需要释放什么东西。
2,能否显示释放内存?
.net里面是不行的。想必你肯定听过GC的内存管理和释放的算法,有三个generation,和一个专门的线程去处理内存问题。
谢谢, 看来 托管资源占用的托管内存没办法立即释放了,只能等GC 了