2012-10-11 113 views
7

Tengo esta idea al pensar en formas de reciclar objetos. Estoy haciendo esto como un experimento para ver cómo funciona la agrupación de memoria y me doy cuenta de que en el 99% de los escenarios esto es muy innecesario.Mantener el objeto en intento de destrucción de GC

Sin embargo, tengo una pregunta. ¿Hay alguna manera de obligar al GC a mantener el objeto? En otras palabras, ¿puedo decirle al GC que no destruya un objeto y diga en su lugar que se haya creado una nueva referencia en una lista que esté disponible para usar objetos? La cuestión, aunque no he probado esto, es que si añado algo como esto a una lista:

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

se añadirá un puntero a este objeto en la lista, pero si el objeto es destruido obtendré una excepción de puntero nulo porque el objeto ya no está allí. Sin embargo, ¿podría decirle al CG que no recoja este objeto y así conserve el objeto?

Sé que este es el tipo de cosas que la mayoría de los programadores irían "¿por qué diablos harías esto?". Pero, por otro lado, la programación se trata de probar cosas nuevas y aprender cosas nuevas. ¿Alguna sugerencia, pensamiento, implementación? ¡Cualquier ayuda sería muy apreciada!

Respuesta

6

Sí, esto es legítimo. Se llama 'resurrección'. Cuando asigna la referencia this a un lugar que está 'activo', entonces el objeto ya no se considera basura.

También necesitará volver a registrar para la finalización usando GC.ReRegisterForFinalize(this), o la próxima vez que el objeto se convierta en basura, no se finalizará (no se llamará al destructor).

Puede leer más sobre la resurrección de objetos en this MSDN Magazine article.

0

El GC solo se ocupará de los objetos cuya referencia haya desaparecido ya sea saliéndose del alcance de ser liberados explícitamente.

De cualquier forma, querrá consultar los métodos KeepAlive y SuppressFinalize para evitar que el GC extraiga sus objetos. Una vez que hayas terminado con ellos, deberás registrarlos para que el recolector los recoja usando ReRegisterForFinalize.

+0

SuprimirFinalizar simplemente cancela la ejecución del destructor, no de la colección. KeepAlive es mejor, pero debes llamarlo a otro lugar, no es práctico. –

2

Sí, esto es posible e incluso tiene un nombre: resurrección.

pero si se destruye el objeto recibiré una excepción de puntero nulo porque el objeto ya no está allí.

Mucho peor, obtendría un error de puntero no válido (referencia). Y posiblemente una pantalla azul o un servidor bloqueado. Pero afortunadamente, el CLR no permitirá que eso suceda. Simplemente colocar una instancia condenada en cualquier tipo de lista la hace accesible nuevamente y luego no será recuperada.

Cuando desee que su objeto sea reciclado varias veces, tendrá que llamar al GC.ReRegisterForFinalize(x).

La respuesta más práctica es: no lo hagas. Solo el destructor representa una sobrecarga considerable y hay muchas formas de equivocarse.

Cuestiones relacionadas