首页 新闻 会员 周边

对 IDisposable接口的疑惑

0
悬赏园豆:80 [已解决问题] 解决于 2012-10-23 11:47

这是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

希望各位园友 指点一下

 

Qlin的主页 Qlin | 老鸟四级 | 园豆:2403
提问于:2012-10-23 09:55
< >
分享
最佳答案
0

问题1:你所说的都是对的。这里component是一个“包含了非托管资源的托管资源”,它本身是托管资源,只不过包含了非托管资源。为此我特地去看了一下你发的链接的英文版,发现这里其实是个英文的理解问题。把注释换成这样应该就能理解了:

//如果等于true,则处理所有“包含了非托管资源的托管资源”和“本身的纯非托管资源”
if(disposing)
{
      //处理包含非托管资源的托管资源
      component.Dispose();
}

//以下是处理非托管资源

问题2:GC会把“没有用的”托管资源统一回收处理。这里你说的“释放”一词有不明确的含义。你可以通过把变量指向null,使堆上的某个对象不再有任何引用指向它,从而它被GC认为是“没有用的”而被回收掉。但是严格来讲并不是“a = null;"这句”释放”了托管资源,它只是不再指向托管资源,虽然这样做的后果是托管资源被认为是垃圾而被回收了。

收获园豆:60
水牛刀刀 | 大侠五级 |园豆:6350 | 2012-10-23 10:29

1.  你的意思是说  IDisposable的Dispose方法只能释放非托管资源吗?

那一个没有包含非托管资源的类实现了IDisposable 接口,有什么影响吗,如性能...?

2. 释放托管资源的意思是说释放托管内存,把它占有的内存释放掉,不能显示释放吗?只能等GC来释放?

Qlin | 园豆:2403 (老鸟四级) | 2012-10-23 10:38

@Qlin: 1. 并非“只能”,而是“只需要”,你在Dispose方法里把一些内部成员设置成null,也是可以的,但是还是等待GC回收,并没有立即回收。2.不能直接释放内存,只能通过GC。

水牛刀刀 | 园豆:6350 (大侠五级) | 2012-10-23 10:53

@水牛刀刀: 

飞常谢谢

Qlin | 园豆:2403 (老鸟四级) | 2012-10-23 11:17
其他回答(2)
0
收获园豆:10
az235 | 园豆:8483 (大侠五级) | 2012-10-23 09:59

文章很好,我的问题里面说的 也不是很清楚。

大侠能直接说说你的理解 好吗?

1. IDisposable 只能释放所有的非托管资源,而不包含托管资源,是不是?

2. 托管资源只能由Gc定期来释放吗? 能不能手动释放,跟调用Dispose方法类似的,有木有?

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-10-23 10:07
0

看你总结起来就两个疑惑:

1,Dispose释放什么资源?

都可以。就看你如何实现你的代码逻辑。非托管资源的释放一般都是通过调用native的api去释放的,而托管的一般都是让堆内存不再被引用就可以了。这里让你困惑的可能是为什么component还要调用dispose去释放,原因是component里面可能需要释放的非托管资源,就看component的dispose怎么实现了,因为它自己最清楚需要释放什么东西。

2,能否显示释放内存?

.net里面是不行的。想必你肯定听过GC的内存管理和释放的算法,有三个generation,和一个专门的线程去处理内存问题。

收获园豆:10
Ethan轻叹 | 园豆:996 (小虾三级) | 2012-10-23 10:58

谢谢, 看来 托管资源占用的托管内存没办法立即释放了,只能等GC 了

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2012-10-23 11:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册