7

我在思考回收物品的方法时产生了这个想法。我这样做是为了看看内存池是如何工作的,我意识到在 99% 的情况下这是非常不必要的。

但是,我有一个问题。有没有办法强制 GC 保留对象?换句话说,我可以告诉 GC 不要销毁一个对象,而是说在一个列表中创建了一个新的引用来保存可使用的对象吗?问题是,虽然我没有对此进行测试,但如果我将这样的内容添加到列表中:

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

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

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

4

3 回答 3

6

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

您还需要使用 重新注册以进行终结GC.ReRegisterForFinalize(this),否则下次对象变为垃圾时,它将不会被终结(不会调用析构函数)。

您可以在这篇 MSDN 杂志文章中阅读有关对象复活的更多信息。

于 2012-10-11T21:37:23.037 回答
2

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

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

更糟糕的是,你会得到一个无效的指针(引用)错误。并且可能是蓝屏或崩溃的服务器。但幸运的是,CLR 不会让这种情况发生。只需将一个注定失败的实例放在任何类型的列表中,它就可以再次访问,然后它就不会被回收。

当您希望您的对象被多次回收时,您将不得不调用GC.ReRegisterForFinalize(x)它。

但最实际的答案是:不要这样做。仅析构函数就占了相当大的开销,并且有很多方法可以解决这个问题。

于 2012-10-11T21:37:17.360 回答
0

GC 只会处理那些引用已经消失的对象,无论是否超出了显式释放的范围。

无论哪种方式,您都需要查看KeepAliveSuppressFinalize方法,以防止 GC 对您的对象进行垃圾收集。一旦你真正完成了它们,你需要使用ReRegisterForFinalize注册它们以供收集器拾取。

于 2012-10-11T21:36:13.090 回答