技术开发 频道

.NET框架下的自动内存管理

 上面的程序创建了类A与类B的一个实例,当变量b被赋于null值时,A与B均符合了垃圾回收器的回收要求。此时就没有任何代码能够访问它们了。

  执行的结果,下面两种情况都有可能:

  Destruct instance of A

  Destruct instance of B

  与

  Destruct instance of B

  Destruct instance of A

  因为上面的程序的并没有限制这两个对象被回收的顺序。

  在某些敏感的条件下,有关区分“销毁”与“回收”操作条件的定义是非常重要的:

  class A
  {

  
~A() {

  Console.WriteLine(
"Destruct instance of A");

  }

  
public void F() {

  Console.WriteLine(
"A.F");

  TMest.RefA
= this;

  }

  }

  
class B

  {

  
public A Ref;

  
~B() {

  Console.WriteLine(
"Destruct instance of B");

  Ref.F();

  }

  }

  
class TMest

  {

  
public static A RefA;

  
public static B RefB;

  
static void Main() {

  RefB
= new B();

  RefA
= new A();

  RefB.Ref
= RefA;

  RefB
= null;

  RefA
= null;

  
// A and B now eligible for destruction

  GC.Collect();

  GC.WaitForPendingFinalizers();

  
// B now eligible for collection, but A is not

  
if (RefA != null)

  Console.WriteLine(
"RefA is not null");

  }

  }

 

   在上面的程序中,如果垃圾回收器选择先执行类B的销毁器,那么执行的结果为:

Destruct instance of A

  Destruct instance of B

  A.F

  RefA
is not null

  注意,虽然实例A并没有被使用,但是从输出的结果大家可以看到A的销毁器确实执行了,而且连A的方法F也被执行了。同时我们也注意至,一个对象销毁器的运行又可能使一个实例变得可用。在这种情况下,实例B销毁器的执行使得先前并没有调用的实例A也可以被访问了,而这一种就是引用RefA的功劳,当调用WaitForPendingFinalizers方法以后,实例B就可以被垃圾回收器回收,而此时的实例A则还不可以。

  为了区分这些行为,大家编写程序时,最好只管理当前类的销毁器,而不要采用引用其它类的实例或者静态字段。

0
相关文章