2010-02-26 15 views
18

GC es para objetos administrados y Finalize es para objetos no administrados, eso es lo que he estado leyendo. Deshacer es implícito y Finalizar es explícito es lo que he estado leyendo. ¿Alguien puede darme un ejemplo de un módulo en el que las tres cosas se han utilizado por diferentes razones?¿Cuál es la relación entre GC, Finalize() y Dispose?

+4

También podría agregar 'Using' en la mezcla mientras está en ello. – RedFilter

Respuesta

25

GC es la recolección de basura. Es la administración de memoria automática, que maneja la limpieza de los objetos asignados en el montón administrado. El .NET GC emplea un algoritmo de marca y barrido. Cuando se produce una recolección de basura, básicamente considera todos los objetos en la parte del montón a limpiar como recuperables. Luego pasa por un proceso de marcado donde escanea en busca de raíces. Es decir. identifica objetos que aún están en uso por la aplicación. Una vez hecho esto, los objetos restantes son elegibles para la limpieza. El montón puede compactarse como parte de la limpieza.

Desechar y métodos Finalizer ambos ofrecen una opción para los recursos de limpieza, que son no manejado por GC. P.ej. esto podría ser identificadores nativos y similares. No tienen nada que ver con reclamar memoria en el montón administrado.

Eliminar debe llamarse explícitamente en un tipo que implemente IDisposable. Se puede llamar a través del método Dispose() o mediante el constructo using. El GC no llamará a Dispose automáticamente.

un finalizador o destructor (como la especificación del lenguaje lo llama), por otro lado se llamará automáticamente en algún momento después de que el objeto era elegible para la limpieza. Los métodos de finalización se ejecutan secuencialmente en un hilo dedicado.

Dispose() permite una limpieza determinística de los recursos, mientras que un finalizador puede actuar como una red de seguridad en caso de que el usuario no llame al Dispose().

Si un tipo implementa un finalizador, la limpieza de las instancias se demora ya que se debe llamar al finalizador antes de la limpieza. Es decir. requerirá un cobro adicional para reclamar la memoria para instancias del tipo. Si el tipo implementa IDisposable también, se puede invocar el método Dispose y luego la instancia puede eliminarse de la finalización. Esto permitirá que el objeto se limpie como si no tuviera un finalizador.

Si quieres profundizar en esto, te recomiendo CLR via C# by Jeffrey Richter. Es un gran libro y cubre todos los detalles sangrientos de esto (omití una serie de detalles). La 3ª edición acaba de ser lanzada.

+1

+1, pero puede agregar que puede suprimir el finalizador con GC.SupressFinalize, que es algo que le gustaría hacer si descarta explícitamente la instancia. –

+0

Si se llama automáticamente a Finalize cuando un objeto es elegible para la limpieza, ¿por qué C no lo hace? Si es un proceso automático? – TeaLeave

+0

No se llama inmediatamente. Está programado para ser llamado. Puede tomar un tiempo antes de que se ejecute. –

7

Es posible que desee leer lo que considero el artículo definitivo sobre IDisposable, finalizadores y recolección de basura, Shawn Farkas 'CLR Inside Out: Digging into IDisposable.

Este artículo deja muy pocas dudas sobre el tema.

+2

Hola Mark, la diferencia entre Dipose() y otras dos es lo que entendí pero lo que estoy luchando es entender la diferencia entre Finalize() y Garbage Collector(). porque hay muchos artículos que encontré donde el autor decía que GC finalmente usa Finalize() para borrar los objetos. Entonces, ¿cuál es la diferencia entre mantener Finalize() en la definición de clase y NO mantener uno porque aunque no guarde Finalize() en mi definición de clase, GC finalmente llama a Finalize() para eliminar el objeto no utilizado. – TeaLeave

+0

Ahora, en alguna parte, leí que los objetos con Finalize() se pondrán en "Cola de finalización" y, cuando el objeto ya no se necesite, la memoria se recuperará GC. – TeaLeave

+0

Las cosas parecen tan entremezcladas porque GC es usign Finalize() y Finalize usa GC :). Estoy confundido ......... – TeaLeave

8

Uno de los beneficios de .NET es el recolector de basura. En muchos idiomas, cada parte de la memoria debe ser administrada por el desarrollador, eventualmente cualquier memoria asignada debe ser liberada. En .NET (C#), el Garbage Collector (GC) se ocupará del proceso de liberar memoria para usted. Realiza un seguimiento del uso de sus objetos y, una vez que se vuelven "desarraigados" (es decir, no hay referencias directas o indirectas en su aplicación a ese objeto), la memoria del objeto se limpia automáticamente.

Desechar, o más particularmente, IDisposable y el patrón Dispose, se utiliza para manejar recursos por separado del GC. Algunos recursos deben ser limpiados explícitamente, por varias razones. Esto incluye el uso de una API "nativa" (donde.NET no sabe acerca de la memoria asignada), utilizando un recurso que envuelve identificadores nativos, etc. Para manejar esto limpiamente, implementa IDisposable y el patrón Dispose.

La finalización se produce en los objetos cuando están a punto de ser recogidos por el recolector de basura. Esto proporciona una "red de seguridad" donde un objeto que debería haber sido eliminado aún puede limpiarse, si es un poco más tarde que lo ideal. Al implementar un finalizador, puede garantizar que los recursos no administrados siempre se liberen.

El problema con la mayoría de las muestras es que existen múltiples razones para usar IDisposable, y la implementación adecuada varía según el motivo por el que la está utilizando. Por ejemplo, si ajusta un recurso nativo directamente, debe implementar un finalizador, pero si encapsula otro tipo ID identificable, no es necesario un finalizador, aunque aún debe implementar IDisposable. Para abordar esto, he escrito sobre IDisposable and finalization in depth on my blog, describiendo las múltiples razones por las que usaría IDisposable, y diferentes patrones por diferentes razones.

Cuestiones relacionadas