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意义何在
--------------------编程问答--------------------
清理非托管资源虽然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进行任何的处理
也就是说,析构函数是个摆设,除非您手动调用以外他会一直在哪里 --------------------编程问答--------------------
GC自动调用回收(从而也就自动地调用dispose)是有延迟的,而这种延迟对于例如SqlDbConnection对象这种就会造成“连接池用尽”的BUG。需要保证立即关闭,所以使用using,可以确保立即调用dispose,从而立即关闭逻辑连接。
其实并不用过度纠结于什么“非托管”之类的概念。因为即使不显示调用IDisposable接口,GC在调用对象的Finally的时候,这个方法通常也会自动调用这个接口。因此不管“是还是不是”什么非托管概念,都跑不掉被调用所谓的dispose方法,并没有区别。
比如不管是托管的SqlDbConnection,那是非托管的windows绘图画刷资源,如果不及时调用释放语句就会造成资源用尽从而发生运行时异常,这时候就都需要using结构的语法来保证任何情况下都会显示调用dispose。
跟托管、非托管没有半点关系。 --------------------编程问答--------------------
这个说法是错误的。
不是纠结什么“非托管,所以需要显示释放”。
你从一开始的代码已经看到了,假设不显示调用dispose,那么在析构函数也会调用dispose。而假设显示调用了dispose,那么代码 GC.SuppressFinalize(this) 就会通知 GC 没有必要再调用析构函数了。
这跟什么非托管没有半点关系。不是什么“因为非托管代码所以就必须显示调用dispose”,不是的。 --------------------编程问答-------------------- 显示调用 --> 显式调用 --------------------编程问答-------------------- 两边还不够回的,还得会三遍,真服了楼上的了
补充:.NET技术 , C#