.net中对象占用资源的回收
程序员文章站
2022-06-30 17:02:26
一,使用Finalizer析构器
1,使用了Finalizer析构器的对象如何被回收?
在类中定...
一,使用Finalizer析构器
1,使用了Finalizer析构器的对象如何被回收?
在类中定义了析构器的对象将会被移动到一个专门的队列中,这个队列将作为它的应用程序根,而使队列中的对象存活的更久一点,在对象上面调用完析构函数后,对象才会从队列中清理掉。
2,使用示例
class Program
{
static void Main(string[] args)
{
Cup cup = new Cup() {
CupName=lhc的小杯子~~~~
};
}
}
public class Cup {
public string CupName { get; set; }
~Cup() {
//此处放置析构代码:对比C++的析构函数,感觉意思是一样的
//这里放置释放资源的代码
Console.WriteLine(小杯子已被打碎~~~~么么哒~~~~~);
}
}
感觉从语法上很像C++,嘿嘿~
3,使用析构器该注意哪些问题?
1,开发这无法确切的得知析构函数何时会被调用
2,析构函数会延长对象的存活时间
3,不要在析构函数中编写阻塞方法或耗时的方法,析构函数应该是迅速释放完资源并结束的
4,如果程序运行期间一直没有进行垃圾回收,那么程序退出时会执行一次垃圾回收,并调用析构函数
二,实现IDisposable接口
Finalizer的执行时间是不确定的,有时候,我们期望客户端对象使用完毕后立即释放资源,此时可以实现Idispose接口。
试用了下这个接口在dispose的时候都会发生啥,感觉还是雷同C++,写个栗子自己观察下析构的时候会发生啥吧。
使用示例:
static void Main(string[] args)
{
#region 构造器使用
//Cup cup = new Cup() {
// CupName=lhc的小杯子~~~~
//};
#endregion
#region dispose的使用
BigCup bigCup = new BigCup()
{
CupName = lhc的小杯子
};
//try
//{
// bigCup.CupName = 此处模拟对象的使用过程;
//}
//finally
//{
// IDisposable dis = bigCup as IDisposable;
// if (dis != null)
// {
// dis.Dispose();
// }
//}
using (bigCup as IDisposable)
{
bigCup.CupName = 此处模拟对象的使用过程;
}
#endregion
}
}
public class BigCup : IDisposable
{
public string CupName { get; set; }
void IDisposable.Dispose()
{
Console.WriteLine(销毁了~~~~);
}
}
三,结合析构函数和Dispose()
析构函数的主要问题在于:它不是立即被调用,而是在以后某个不确定的时间,执行垃圾回收时被调用。Dispose()方法也有自己的问题,就是客户端不一定会调用它。因此,最好的方法就是将这两者结合起来:
如果客户端调用了Dispose()方法,那么就不要让CLR去执行析构函数;
如果客户端没有调用,此时再进行析构。
结合使用Demo:
public class TestFatherFinalizerAndDispose :IDisposable{
private bool _dispose = false;
~TestFatherFinalizerAndDispose() {
Console.WriteLine(调用析构函数~~~~);
}
public void IDisposable.Dispose() {
if (!_dispose)
{
_dispose = true;
CleanUp();
GC.SuppressFinalize(this);//指示垃圾回收期,无视该对象的析构函数。
}
}
//子类可重写该释放资源方法
public virtual void CleanUp() {
//此处放置清理资源代码
Console.WriteLine(垃圾清理完毕~);
}
}
public class TestSonFinalizerAndDispose : TestFatherFinalizerAndDispose {
public override void CleanUp()
{
try
{
Console.WriteLine(此处填写释放子类型资源的方法);
}
finally {
base.CleanUp(); //调用父类的方法释放父类的资源
}
}
}