当前位置:编程学习 > C#/ASP.NET >>

IDisposable写法与资源疑问

摘录
非托管资源
指诸如包装操作系统资源的一类对象,例如文件,窗口或网络连接,对于这类资源虽然垃圾回收器(GC)可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理这些资源。

托管资源
指那些资源的回收工作由.net CLR 的GC 机制自动完成,无需显式释放的资源

问题如下,

        /// <summary>
        /// 析构
        /// </summary>
        ~MyClass()
        {
            Dispose(false); 
        }
        /// <summary>
        /// 释放资源
        /// </summary>

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
//全删了从新写,表达可能有问题看红字
        private void Dispose(bool disposing)
        {

            if (!this.IsDisposed)这里是第一次使用
            {   
                if (disposing)这里区别是,显示还是非显示
                {
                    //清理托管资源
                     int =0;........
                     //这里应该是显示释放资源,既然是托管,那为什么要我释放
                }
                //清理非托管资源
                Transaction.Dispose()......
                无论怎样都释放非托管资源

问题在于托管资源,即使是int=0,int=null,他的对象应该还是存在的,并不能直接清除

那么清理清理托管资源意义何在,显示调用还是非显示调用意义何在

            }
               
            this.IsDisposed = true;
        }


--------------------编程问答-------------------- 清理非托管资源虽然GC看起来是自己释放的,但是非托管资源内部需要实现完善的回收代码,否则GC也只能尽尽地主之谊,不能知道贵客具体是什么身份 --------------------编程问答-------------------- 我用using调试一下,他真的是这个样子的
当我在using时候,他回走完全部
不用using 当他超过域会走析构
这样就绕过了disposing=true方法
完全交给内部回收了
既然可以,完全交给内部回收,那disposing意义何在
--------------------编程问答--------------------
引用 1 楼 mngzilin 的回复:
清理非托管资源虽然GC看起来是自己释放的,但是非托管资源内部需要实现完善的回收代码,否则GC也只能尽尽地主之谊,不能知道贵客具体是什么身份

清理非托管资源虽然GC看起来是自己释放的
您的这句话我怎么看这奇怪啊!!
非托管资源自己释放???
真的可以实现吗 --------------------编程问答-------------------- 代码中的,托管,非托管分离叫我有点绕了
举个例子:
我在一个对象中使用了Transaction
显然他是非托管,需要您显示释放的
而我有一个bool的变量,方便Transaction的显示状态
代码如下
 

bool isOpenT = false
Transaction.BeginTransaction
isOpenT=true

这样问题来了
if (disposing)中如何释放那
吧isOpenT 放在里面
那叫他干什么那!!!
=false,=null
显然不对啊!
放在外面??
他是托管的啊,应该在里面的 --------------------编程问答-------------------- 假设dll中一个c++类AA,内部构造函数中为byte* buf申请了一个100字节的空间,那么他会在析构函数中写释放代码delete[] buf;

如果上面dll被C #调用,回收时候c++内部析构函数会执行回收。
如果你C#定义一个AA a=new AA();AA是dll中的。你不需要自己dispose,他生命周期到了后,GC自己会销毁,同时C++析构函数会将byte*所指向的资源释放。

Transaction当你不用时可以调用dispose()释放就可以了,至于如何释放的你不必关心,既然是非托管,那么必然有如析构这样的过程去处理。 --------------------编程问答--------------------
可能有点绕嘴
他是这个样子的
在回收上,他是先吧您的资源变成垃圾,
然后在在回收,他们是两个独立的部分
您做纠结的disposing是用来显示区分到底是谁在使用
您看您的

bool isOpenT = false
Transaction.BeginTransaction
isOpenT=true

他们的回收应该都是在disposing下面的
外面应该是api之类的手动资源
在Transaction其实也是有disposing,在您Dispose他的默认是true
然后在调用base.Dispose,您一个单类就没有了
这些都是显示调用的,非显示调用,就是说:不知道他什么时候调用
当然他一定会,但是不知道什么时候,最起码要走完当前域
我认为您要去掉disposing也是可以的
在Transaction的内部并没有对false进行任何的处理
也就是说,析构函数是个摆设,除非您手动调用以外他会一直在哪里 --------------------编程问答--------------------
引用 2 楼  的回复:
我用using调试一下,他真的是这个样子的
当我在using时候,他回走完全部
不用using 当他超过域会走析构
这样就绕过了disposing=true方法
完全交给内部回收了
既然可以,完全交给内部回收,那disposing意义何在


GC自动调用回收(从而也就自动地调用dispose)是有延迟的,而这种延迟对于例如SqlDbConnection对象这种就会造成“连接池用尽”的BUG。需要保证立即关闭,所以使用using,可以确保立即调用dispose,从而立即关闭逻辑连接。

其实并不用过度纠结于什么“非托管”之类的概念。因为即使不显示调用IDisposable接口,GC在调用对象的Finally的时候,这个方法通常也会自动调用这个接口。因此不管“是还是不是”什么非托管概念,都跑不掉被调用所谓的dispose方法,并没有区别。

比如不管是托管的SqlDbConnection,那是非托管的windows绘图画刷资源,如果不及时调用释放语句就会造成资源用尽从而发生运行时异常,这时候就都需要using结构的语法来保证任何情况下都会显示调用dispose。

跟托管、非托管没有半点关系。 --------------------编程问答--------------------
引用 4 楼  的回复:
代码中的,托管,非托管分离叫我有点绕了
举个例子:
我在一个对象中使用了Transaction
显然他是非托管,需要您显示释放的
而我有一个。。。。。。


这个说法是错误的。

不是纠结什么“非托管,所以需要显示释放”。

你从一开始的代码已经看到了,假设不显示调用dispose,那么在析构函数也会调用dispose。而假设显示调用了dispose,那么代码 GC.SuppressFinalize(this) 就会通知 GC 没有必要再调用析构函数了。

这跟什么非托管没有半点关系。不是什么“因为非托管代码所以就必须显示调用dispose”,不是的。 --------------------编程问答-------------------- 显示调用  -->  显式调用 --------------------编程问答-------------------- 两边还不够回的,还得会三遍,真服了楼上的了
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,