2012-10-11 62 views
7

我想到了回收对象的方法时就明白了。我正在做这个实验,看看内存池是如何工作的,我意识到在99%的情况下这是非常不必要的。在GC销毁尝试中保留对象

但是,我有一个问题。有没有办法强制GC保留对象?换句话说,我可以告诉GC不要销毁一个对象,而是说在一个列表中创建了一个新的引用,该列表保存了可供使用的对象?这个问题,虽然我没有测试过这一点,就是如果我增加一些像这样的列表:

~myObject() 
{ 
    ((List<myObject>)HttpContext.Current.Items[typeof(T).ToString()]).add(this);//Lets assume this is ASP 
} 

它将一个指针到该对象到列表中,但如果对象被毁灭,那么我会得到空指针异常,因为对象不再存在。但是,也许我可以告诉GC不要收集这个项目,从而保持对象?

我知道这是大多数程序员会去的东西的类型,“为什么你会这样做?”。但另一方面,编程则是尝试新事物和学习新事物。任何建议,想法和实施?任何帮助将不胜感激!

回答

6

是的,这是合法的。它被称为“复活”。当您将this引用分配给“活”的某个位置时,则该对象不再被视为垃圾。

您还需要使用GC.ReRegisterForFinalize(this)重新注册以进行最终确定,或者下次该对象变为垃圾时,它不会被终止(析构函数不会被调用)。

您可以在this MSDN Magazine article中阅读更多关于物体复活的内容。

0

GC只会照顾那些被引用消失的对象,无论是否超出被明确发布的范围。

无论采用哪种方式,您都需要查看KeepAliveSuppressFinalize方法,以防止GC垃圾收集您的对象。一旦你真的完成了他们,你需要注册它们,由收集者使用ReRegisterForFinalize

+0

SuppressFinalize只是取消运行析构函数,而不是集合。 KeepAlive更好,但你必须把它称为某个地方,而不是实际的。 –

2

是的,这是可能的,它甚至有一个名称:复活。

但如果对象被销毁,我将得到一个空指针异常,因为对象不再存在。

更糟糕的是,你会得到一个无效的指针(引用)错误。可能是蓝屏或服务器崩溃。但幸运的是,CLR不会让这种情况发生。简单地将一个注定的实例放在任何一种列表中都会使它再次可达,然后它将不会被回收。

当你想让你的物体多次被回收时,你将不得不打电话给GC.ReRegisterForFinalize(x)

尽管最实际的答案是:不要这样做。单独的析构函数会造成相当大的开销,并且有很多方法可能导致错误。