.Net中的对象处理

时间:2011-07-14 08:01:38

标签: c# .net object dispose

假设我有以下课程:

Class MainClass
{
   private OtherClass1;
   MainClass()
   {
      OtherClass1 = new OtherClass1();
   }

   void dispose()
   {
      OtherClass1 = null;
   }
}

class OtherClass1
{
   private OtherClass2;
   OtherClass1()
   {
      OtherClass2 = new OtherClass2();
   }
}

class OtherClass2
{
}

如果我实例化MainClass并稍后调用dispose方法,那么OtherClass1是否会被垃圾收集(稍后)?或者我是否首先清除对OtherClass2的引用?

5 个答案:

答案 0 :(得分:6)

如果对象没有引用,则会收集垃圾,或者它所引用的引用来自本身没有引用的对象(等等)。

一种可视化方式,垃圾收集器将遍历对象引用图,跟随所有对象引用,记录它所获得的内容(仍然从某处引用)。任何它没有得到的资格都有资格进行垃圾收集,就好像它没有找到它们那么它们就不可能被使用了。

请参阅此处获取深入信息(特别是“垃圾收集算法”):http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

是的,它有资格成为GC。


另外,如果你有一个dispose方法,你真的应该实现IDisposable

答案 1 :(得分:1)

在提供的代码中,您没有null任何内容,您可以安全地删除dispose(),一切都会好的。

如果您的OtherClass1和/或OtherClass2是托管资源,即他们实现了IDisposable接口,那么您的代码就不够好了。然后,您必须链接Dispose:

class MainClass : IDisposable
{
   private OtherClass1;
   MainClass()
   {
      OtherClass1 = new OtherClass1();
   }

   public void Dispose()
   {
      OtherClass1.Dispose(); 
      // OtherClass1 = null;  // not needed
   }
}

答案 2 :(得分:0)

如果没有其他参考,它可能在某个时候被垃圾收集。请注意,这是确定性,您不能依赖于在特定时间段内收集它。

一般情况下,你不必过于担心,.NET中的GC可以通过设计处理循环引用等而没有任何问题。通常不需要将字段设置为nullDispose方法通常用于以确定的方式释放非托管资源,例如数据库连接等;它不是要释放被处理物体的记忆。

答案 3 :(得分:0)

最佳实践是实现IDisposable接口并实现Dispose()方法。

在Dispose()中,您只需释放对象使用的资源,例如任何外部资源,COM引用,数据库连接等。

就对象何时进行垃圾收集而言,由.NET引擎决定是否经常在每次发布时更新其处理算法。

通常,当一个对象是孤儿(没有变量引用它)时,它将在队列中被垃圾收集。

您可以手动调用GC.Collect();但不建议这样做,因为它会干扰.NET垃圾收集机制。

答案 4 :(得分:-2)

“Dispose”这个术语有点用词不当,因为Dispose方法不会删除目标对象,而是要求目标对象做任何在安全放弃之前需要完成的事情。 。从本质上讲,它是一个请求对象将其事务按顺序排列。

当一个特定对象需要将其事务整理好时,最常见的情况是当它之外的某些实体可能正在做某事,存储某些东西,避免做某事,或以其他方式暂时改变它们的行为时。请注意,实体可能是.net对象,其他类型的OS识别对象(GDI句柄等)等,但没有特别要求实体是任何特定类型的东西,也不是它们在同一台计算机中,甚至任何电脑。对于使其事务井然有序的对象,需要告知外部实体代表其执行,持有等任何事情,他们不再需要这样做。如果有问题的实体是实现IDisposable的.net对象,通常通过调用它们的Dispose方法来执行通知。

请注意.net提供了一种方法,通过该方法,如果系统注意到它们已被放弃,则可以通过这些方式通知对象,并将其用作提示将其事务按顺序排列的提示。此类通知可能不及时,并且各种因素可能导致它们基本上无限期地延迟,但这种机制(称为“终结”)有时比没有更好。