C#学习-关于析构函数,Dispose,和Close
C# 中的析构函数实际上是重写了 SystemFinalize.Object 中的虚⽅法 Finalize
三种最常的⽅法如下:
1. 析构函数;(由GC调⽤,不确定什么时候会调⽤)
2. 继承IDisposable接⼝,实现Dispose⽅法;(可以⼿动调⽤。⽐如数据库的连接,SqlConnection.Dispose(),因为如果及时释放会影响数据库性能。这时候会⽤到这个,再如:⽂件的打开,如果不释放会影响其它操作,如删除操作。调⽤Dispose后这个对象就不能再⽤了,就等着被GC回收。)
3. 提供Close⽅法。(类似Dispose但是,当调⽤完Close⽅法后,可以通过Open重新打开)
析构函数不能显式调⽤,⽽对于后两种⽅法来说,都需要进⾏显⽰调⽤才能被执⾏。⽽Close与Dispose这两种⽅法的区别在于,调⽤完了对象的Close⽅法后,此对象有可能被重新进⾏使⽤;⽽Dispose⽅法来说,此对象所占有的资源需要被标记为⽆⽤了,也就是此对象要被销毁,不能再被使⽤。例如常见.Net类库中的SqlConnection这个类,当调⽤完Close⽅法后,可以通过Open重新打开⼀个数据库连接,当彻底不⽤这个对象了就可以调⽤Dispose⽅法来标记此对象⽆⽤,等待GC回收。明⽩了
这两种⽅法的意思后,⼤家在往⾃⼰的类中添加的接⼝时候,不要歪曲了这两者意思。
析构函数Dispose⽅法Close⽅法意义销毁对象销毁对象关闭对象资源
调⽤⽅式不能被显⽰调⽤,在GC回收是被调⽤需要显⽰调⽤
或者通过using语句
需要显⽰调⽤
调⽤时机不确定确定,在显⽰调⽤或者离开using程序块确定,在显⽰调⽤时下⾯提供⼀个模式来结合上⾯的 析构函数和Dispose⽅法。
public class BaseResource: IDisposable
{
//前⾯我们说了析构函数实际上是重写了 System.Object 中的虚⽅法 Finalize, 默认情况下,⼀个类是没有析构函数的,也就是说,对象被垃圾回收时不会被调⽤Finaliz ~BaseResource()
{
// 为了保持代码的可读性性和可维护性,千万不要在这⾥写释放⾮托管资源的代码
// 必须以Dispose(false)⽅式调⽤,以false告诉Dispose(bool disposing)函数是从垃圾回收器在调⽤Finalize时调⽤的
Dispose(false);
}
// ⽆法被客户直接调⽤
// 如果 disposing 是 true, 那么这个⽅法是被客户直接调⽤的,那么托管的,和⾮托管的资源都可以释放
// 如果 disposing 是 false, 那么函数是从垃圾回收器在调⽤Finalize时调⽤的,此时不应当引⽤其他托管对象所以,只能释放⾮托管资源
false是什么函数 protected virtual void Dispose(bool disposing)
{
// 那么这个⽅法是被客户直接调⽤的,那么托管的,和⾮托管的资源都可以释放
if(disposing)
{
// 释放托管资源
OtherManagedObject.Dispose();
}
//释放⾮托管资源
DoUnManagedObjectDispose();
// 那么这个⽅法是被客户直接调⽤的,告诉垃圾回收器从Finalization队列中清除⾃⼰,从⽽阻⽌垃圾回收器调⽤Finalize⽅法.
if(disposing)
GC.SuppressFinalize(this);
}
//可以被客户直接调⽤
public void Dispose()
{
//必须以Dispose(true)⽅式调⽤,以true告诉Dispose(bool disposing)函数是被客户直接调⽤的
Dispose(true);
}
}
1) 如果客户没有调⽤Dispose(),未能及时释放托管和⾮托管资源,那么在垃圾回收时,还有机会执⾏Finalize(),释放⾮托管资源,但是造成
了⾮托管资源的未及时释放的空闲浪费
2) 如果客户调⽤了Dispose(),就能及时释放了托管和⾮托管资源,那么该对象被垃圾回收时,不回执⾏Finalize(),提⾼了⾮托管资源的使
⽤效率并提升了系统性能
最后:
如果您的类中使⽤了⾮托管资源,则要考虑提供Close⽅法,和Open⽅法。并在您的Dispose⽅法中先调⽤ Close⽅法。
在使⽤已经 有类时,如SqlConnection。如果暂时不⽤这个连接,可以考虑⽤Close()⽅法。如果不⽤了就考虑调⽤
Dispose()⽅法。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论