pattern net example collector .net garbage-collection dispose

.net - net - implements idisposable dispose c#



¿Cuándo debería disponer mis objetos en.NET? (8)

Para el código general, ¿realmente necesito deshacerme de un objeto? ¿Puedo ignorarlo en su mayor parte o es una buena idea desechar siempre un objeto cuando esté 100% seguro de que ya no lo necesita?


Confiar en el GC ''funciona'' en la mayoría de los casos. La excepción clásica es cuando tienes una interacción de recurso pesado: en ese caso, lo mejor es disponer explicitamente.

obvio, por ej.

using (var conn = new SqlConnection(connString)) {}

Los bloques "de uso" son definitivamente el método más limpio y sólido para garantizar que los objetos se eliminen correctamente. Los bloques ''Using'' se pueden aprovechar con cualquier objeto que implemente IDisposable.


Cuando termines con un objeto, puedes olvidarte de él. Siempre y cuando no se haga referencia en ningún lugar, ya está perdido. La memoria que utiliza se libera cuando el recolector de basura lo desea.


Deshazte de un objeto en el instante en que hayas terminado con él. Los objetos desechables representan objetos que contienen un recurso valioso del cual el CLR no es intrínsecamente consciente. En consecuencia, el GC también desconoce los recursos y no puede tomar decisiones inteligentes sobre cuándo debe recoger un objeto desechable y, por lo tanto, liberar el recurso subyacente.

Eventualmente, el GC sentirá la presión de la memoria y recogerá su objeto por coincidencia (nada más). Si no se deshace de los objetos de una manera determinista, entonces es completamente posible ingresar a un estado de escasez de recursos con casi ninguna presión de memoria.

Ejemplo rápido de cómo puede suceder esto. Pensemos en el recurso subyacente como el manejo de Win32. Estos son muy finitos y bastante pequeños. Ejecuta una operación que crea muchos objetos Foo. Los objetos Foo implementan IDisposable y son responsables de crear y deshacerse de un identificador de Win32. No se liberan manualmente y por una peculiaridad diferente lo convierten en el montón Gen2. Este montón se libera con bastante poca frecuencia. Con el tiempo, bastantes instancias de Foo llegan al montón Gen2 para ocupar todos los identificadores disponibles. Por lo tanto, no se pueden crear nuevos objetos Foo independientemente de la cantidad de memoria que se use.

De hecho, para liberar las asas, se necesitaría asignar una gran cantidad de memoria durante una sola operación para dar suficiente presión para liberar las instancias.


Hay un par de maneras de verlo. Una manera de averiguar si es realmente necesario deshacerse de un objeto tan pronto como ya no lo necesite, por ejemplo, utilizando Reflector para ver si realmente se está reteniendo en recursos no administrados, o si de todos modos se eliminaron de manera incidental. La otra perspectiva es suponer que si un objeto implementa IDisposable, no es su responsabilidad determinar si realmente necesita llamarse a Dispose (), siempre lo llama. Creo que ese es el camino correcto a seguir. Mirar detenidamente la implementación privada de los objetos para tomar decisiones sobre cómo debe consumirlos aumenta el riesgo de que se acople a una implementación que podría cambiar. Un ejemplo es LINQ to SQL DataContext. Implementa IDispose pero principalmente limpia después de sí mismo sin la necesidad de una llamada explícita a Dispose (). Mi preferencia es escribir código que explícitamente disponga de todos modos, pero otros han sugerido que no es necesario.

Por supuesto, todo esto se aplica a los objetos que implementan IDisposable. Es cierto que el GC se encargará de casi todo lo demás sin ninguna acción explícita de su parte, pero vale la pena leer un poco sobre las sutilezas del comportamiento del GC (estoy demasiado cansado para pensar en los detalles ahora mismo) para saber cuándo deshacerse de los objetos explícitamente, y más importante aún, cuándo implementar IDispose. Hay muchos buenos artículos sobre interwebs sobre el tema.

Y como dije anteriormente, usar (...) {...} es su amigo para implementadores IDisposables.


La razón por la que siempre debe llamar a Dispose() en cualquier tipo que implemente IDisposable , es que generalmente se usa para indicar que el tipo adquiere recursos no administrados. Es especialmente importante que estos sean liberados, y tan pronto como sea posible. Como otros han mencionado, el using es la forma preferida de hacerlo.


No, puede salirse con la vocación Dispose en los casos en que no tenga un recurso no administrado. Pero si su clase tiene un recurso no administrado, por ejemplo, un archivo temporal que debe eliminarse, deberá llamar explícitamente a Dispose.

Puede evitar llamar a Dispose escribiendo su código de liberación en el método Finalize, pero luego depende del Garbage Collector porque nunca está seguro de cuándo Garbage collector finalizará su objeto. Para estar seguro, si está diseñando una clase que contiene un recurso no administrado, puede escribir el mismo código de liberación de objeto en ambos métodos Dispose y Finalize, pero si lo hace, siempre use SuppressFinalize () en su método de eliminación porque evitará que se llame al método Finalize () si su objeto ya se encuentra en la cola de finalización.


Si el objeto implementa IDisposable, debe deshacerse de él tan pronto como haya terminado con él. La forma más fácil es rodearlo con un bloque de uso :

using (SqlCommand cmd = new SqlCommand(conn)) { cmd.ExecuteNonQuery(); }


Si el objeto implementado IDisposable, es bastante probable que se aferre a recursos no administrados. La regla general, por lo tanto, sería llamar a Dispose en el momento en que haya terminado con el objeto, ya sea directamente o mediante un bloque de uso. No confíe en el GC, ya que para eso es IDisposable: liberación determinística de recursos.