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?¿Cuándo debería disponer de mis objetos en .NET?
Respuesta
Si el objeto implementa IDisposable, debe deshacerse de él tan pronto como haya terminado con él. La forma más sencilla es rodearla de un bloque using:
using (SqlCommand cmd = new SqlCommand(conn)) {
cmd.ExecuteNonQuery();
}
Basándose en la GC 'obras' 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 eg.
using (var conn = new SqlConnection(connString)) {}
Los "bloques de uso" son definitivamente el método más limpio y más robusto para garantizar que los objetos se desechen correctamente. Los bloques 'Using' se pueden aprovechar con cualquier objeto que implemente IDisposable.
Cuando haya terminado con un objeto, puede olvidarse de él. Siempre y cuando no se haga referencia a ningún lugar, ya está perdido. La memoria que utiliza se libera cuando el recolector de basura lo desea.
¿Puede alguien explicar por qué esta respuesta se cerró de esta manera? -6? Y no hay comentarios? – bobobobo
@bobobobo Creo que porque no se está direccionando IDisposable, que está destinado a permitir que un objeto libere recursos externos al .NET Runtime cuando ya no se necesitan en lugar de esperar a GC. – ongle
Hay un par de maneras de verlo. Una forma 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 aferra a recursos no administrados, o si de todos modos se eliminaron de todos modos. 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, 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 los implementadores IDisposable.
No estoy seguro de por qué votaron aquí. +1 de mi parte –
La razón por la que siempre debe llamar al 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, using
es la forma preferida de hacerlo.
Elimine un objeto en el momento en que termine de utilizarlo. 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 de 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 una gran cantidad de memoria para ser asignada durante una sola operación para dar suficiente presión para liberar las instancias.
System.Drawing clases no informan al GC de la presión de memoria correctamente, por lo que no se priorizan para su eliminación como deberían (se ve un objeto 80mb como 1k o menos) –
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.
No puede salirse con la suya vocación Deseche 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.
En realidad, el método preferido es no repetir el código en su método de finalización y elimine el método, pero impleméntelo como se detalla en este enlace http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx – Sekhat
- 1. ¿Cuándo debería usar transacciones en mis consultas?
- 2. Patrón de repositorio en Entity framework 4 ¿cuándo deberíamos disponer?
- 3. ¿Cómo disponer una lista de objetos desechables?
- 4. ¿Cuándo debería usar una base de datos de objetos?
- 5. ¿Cuándo debería usar GC.SuppressFinalize()?
- 6. Mejores prácticas: ¿Cuándo debería usar un delegado en .NET?
- 7. ¿Cuándo debería implementar IDisposable?
- 8. Cuándo/Por qué no debería usar IsReference = true en mis DataContracts?
- 9. EF, UoW y repositorio: ¿cuándo disponer el UnitOfWork en WebForms?
- 10. ¿Debería deshacerse de los objetos jQuery?
- 11. ¿Debería destruir mis antecedentes?
- 12. ¿Cuándo puedo disponer de un control WPF IDisposable, p. WindowsFormsHost?
- 13. ¿Cuándo debería usar # en ColdFusion?
- 14. ¿Cuándo debería escribir métodos estáticos?
- 15. ¿Cómo puedo disponer System.Xml.XmlWriter en PowerShell
- 16. ¿Cuándo debería usar stdClass y cuándo debería usar una matriz en php oo?
- 17. ¿Cuándo debería usar _aligned_malloc()?
- 18. Cuándo debería implementar __call__
- 19. ¿Cuándo debería usar semáforos?
- 20. ¿Cuándo debería usar ConcurrentSkipListMap?
- 21. ¿Cuándo debería usar CompiledQuery?
- 22. ¿Cuándo debería iniciarse RVO?
- 23. ¿Cuándo debería especificar explícitamente StructLayout?
- 24. Cuándo debería usar SynchronousQueue
- 25. Debería declarar explícitamente mis variables en VB6
- 26. ¿Cuándo debería usar Silverlight y cuándo XNA?
- 27. ¿Cuándo debería usar TCP_NODELAY y cuándo TCP_CORK?
- 28. ¿Cuándo debería liberar objetos en - (nulo) viewDidUnload en lugar de en -dealloc?
- 29. ¿Cuándo y por qué debería usar TStringBuilder?
- 30. En Objective-C, ¿cuándo debería usar métodos de clase y cuándo debería usar métodos de instancia?
El GC funciona por pura coincidencia. No tiene ninguna obligación de llamar a Dispose de manera oportuna. – JaredPar
No sugerí que el CG estuviera obligado a hacerlo de manera oportuna. Estoy de acuerdo con mi afirmación de que la eliminación de objetos comunes es innecesaria. – berko
Entonces, por ejemplo, cuando crea una instancia de Bitmap, ¿no cree que necesita deshacerse de ella manualmente? Piensa otra vez. El GC ve ese objeto de 30MB como 10 bytes y lo ignora indefinidamente. Se bloqueará su servidor cada vez. –