技术开发 频道

.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
相关文章