vlambda博客
学习文章列表

详解.NET垃圾回收器GC、析构函数(Finalize 方法)和Dispose

    托管资源指的是.NET Framework可以自动进行回收的资源,主要是指托管堆上分配的内存资源。非托管资源指的是.NET Framework不知道如何回收的资源,本文主要介绍.NET(C#) 中资源回收相关的垃圾回收器GC、析构函数(Finalize 方法)和Dispose。


1、垃圾回收器GC

GC(Garbage Collection)是.NET中的垃圾回收器。以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别它们是否被引用,来确定哪些对象是已经死亡的,哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。GC的开销通常很大,而且它的运行具有不确定性,微软的编程规范里是强烈建议你不要显式调用GC。但你的代码中还是可以使用.NET Framework中GC的某些方法进行手动回收,前提是必须要深刻理解GC的回收原理,否则手动调用GC在特定场景下很容易干扰到GC的正常回收甚至引入不可预知的错误。

在.NET Framework中,创建对象所用内存在托管堆中分配,垃圾管理器负责管理。在堆中可分配的内存,被CLR以块划分,以代[Gemeration]命名,初始分为256k、2M和10M三个代(0、1和2)。并且CLR可以动态调整代的大小。在堆创建的每一个对象都有一个Generation的属性。.NET Framework中约定,最近创建的对象,其Generation其值为0。创建时间越远代数越高。

强制垃圾回收用函数GC.Collect()GC.Collect(int32)参考为Generation,代码如下,

using System; using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.IO; namespace ConsoleApplication{ public class TestObject  { public int Value = 100; public string Key = "cjavapy"; } class Program { static void Main(string[] args) { TestObject obj = new TestObject(); int generation = 0 ;  generation = GC.GetGeneration(obj); Console.WriteLine(0); Console.WriteLine( " TotalMemory:{0} " , GC.GetTotalMemory( false )); Console.WriteLine( " MaxGeneration:{0} " , GC.MaxGeneration); Console.WriteLine( " Value:{0},Key:{1} " , obj.Value, obj.Key.Length); Console.WriteLine( " Generation:{0} " , generation); Console.WriteLine();  try { new FileStream(@"F:\cavapy.avi", FileMode.Open); } catch (Exception e) { }  for ( int j = 1 ; j < 6 ; j ++ ) { generation = GC.GetGeneration(obj); Console.WriteLine(j.ToString()); Console.WriteLine( " TotalMemory:{0} " , GC.GetTotalMemory( false )); Console.WriteLine( " MaxGeneration:{0} " , GC.MaxGeneration); Console.WriteLine( " Value:{0},Key:{1} " , obj.Value, obj.Key.Length); Console.WriteLine( " Generation:{0} " , generation); Console.WriteLine(); GC.Collect(); GC.WaitForPendingFinalizers(); } Console.ReadKey();  } }}

2、析构函数(Finalize 方法)

析构函数(Finalize 方法)用来释放非托管资源,由GC来调用执行回收,来保证非托管资源可以被释放。Object.Finalize()方法是无法重载的,编译器是根据类的析构函数来自动生成Object.Finalize()方法的。对于包含非托管资源的类,可以将释放非托管资源的代码放在析构函数。

例如,

public class FinalizeClass{ ~FinalizeClass() { //在这里,清理非托管资源 }}

注意:不能在析构函数中释放托管资源,因为析构函数是由垃圾回收器调用的,可能在析构函数调用之前,类包含的托管资源已经被回收了,从而导致无法预知的结果。

3、Dispose

.NET Framework中非托管理资源的释放,除了可以使用析构函数(Finalize 方法),还可以通过实现IDisposable接口,代码执行完成后通过调用Dispose()方法来释放非托管资源。与析构函数的区别主要是,Dispose()方法需要程序员手动调用。

调用方式如下,

//方式1:显示接口调用SomeType st1=new SomeType();//执行操作st1.Dispose(); //方式2:using()语法,运行到using范围外自动执行Dispose方法using (var st2 = new SomeType()){ //执行操作}

出处:https://www.cjavapy.com/article/2526/


支持小微:


腾讯云 爆款2核2G云服务器首年40,2G4核云服务器298元/3年

链接:https://curl.qcloud.com/1VVs7OBH


右下角,您点一下在看图片

小微工资涨1毛

商务合作QQ:185601686