.net - net - IDisposable, ¿realmente importa?
override void dispose (9)
Viniendo de C / C ++ hace mucho tiempo, todavía tengo el hábito de asegurar que todos los recursos se limpien correctamente. Siempre me aseguro de que se utiliza Dispose en las clases IDisposable e implemento los patrones Dispose en mis clases que contienen objetos desechables.
Sin embargo, en mi entorno soy más o menos el único que hace esto. Otros simplemente no entienden lo que estoy haciendo y piensan que mi código es más difícil de entender.
Simplemente crean conexiones de bases de datos, abren streams, etc. sin llamar a Close o Dispose. A veces establecen una variable local o miembro a "Nothing" al final de un método (adivinar su fondo).
Mi problema es que su código funciona tan bien como el mío. El código que con el tiempo crea miles de objetos de conexión de base de datos simplemente funciona.
Entonces, ignorando cualquier argumento sobre corrección de código, siguiendo lineamientos, etc., ¿realmente importa el IDiposable ?
¿Alguien realmente se ha quedado sin recursos de objetos que no se deshacen?
Editar: Gracias por todas las respuestas. Es interesante ver que algunas personas han tenido problemas cuando no se deshacen. Sin embargo, parece ser raro y supongo que el GC / JIT hace un buen trabajo para mantener el uso de recursos bajo condiciones normales.
Ni mis colegas ni yo cambiaremos el comportamiento debido a esto, pero se siente bien tener razón.
Además de los casos obvios (ya mencionados) de recursos que se están acabando, otro beneficio de IDisposable es que, como garantiza que Dispose () se llama cuando sale un bloque de using
, puedes usarlo para todo tipo de cosas, incluso cosas que no son simplemente "realiza la operación con el recurso del sistema operativo".
De esta forma, es como un sustituto de los pobres para los bloques de Ruby, o para un pequeño caso de uso de las macros de Lisp.
Algunos de estos recursos, como los identificadores, son un recurso limitado para todo el sistema, por lo que si su aplicación no lanza estas otras aplicaciones o incluso el sistema operativo puede sufrir. Eche un vistazo al último artículo de Mark Russinovich sobre los límites de las series de Windows para ver ejemplos.
No desechar (o cerrar) las conexiones de la base de datos eventualmente lo morderá, sí. He visto que eso suceda.
No eliminar los objetos descartables IDisposable de la base de datos es una manera confiable y eficiente de generar OutOfMemoryExceptions en entornos.
DataSet implementa IDisposable y he leído que no es necesario llamar a Dispose porque los objetos que deben eliminarse para un conjunto de datos solo se crean en el momento del diseño (por el diseñador visual del estudio). Nunca he visto OOM a partir de datasets no expuestos (solo OOM de enormes DataSets)
Sí, eso importa. Cuando un objeto implementa IDisposable, declara explícitamente que contiene recursos que deben liberarse cuando el objeto ya no se necesita.
La mayoría todavía limpiará sus recursos cuando el objeto se finalice, pero la finalización no es determinista y no se puede confiar en la gestión de recursos.
Simplemente envolviendo las declaraciones de variables en un bloque using(...)
hace que sea fácil deshacerse de ellas adecuadamente.
Sí, he llegado al máximo de la cantidad de cursores de Oracle al hacer un bucle sobre un objeto de conexión, por ejemplo, porque olvidé cerrar el lector de comandos; eso era solo 100 bucles en una sola conexión, y necesitaba apoyar eso con posiblemente cientos de conexiones haciéndolo al mismo tiempo.
Debe enseñarse a sus compañeros desarrolladores a utilizar la sintaxis using() { ... }
si no pueden molestarse en cerrar ellos mismos los recursos no administrados. De todos modos, es una buena práctica y también debe usarla, ya que usted mismo puede olvidarse de poner sus llamadas a Dispose()
en una cláusula finally {}
para poder limpiar realmente en caso de que se produzca una excepción no controlada.
Si no puede conquistar sus corazones, cambie de opinión, cree pruebas que rompan su código maximizando los recursos que no están limpiando, y luego demuestre que la "solución" es simple y fácil, y habilita su código para ser mucho más escalable. O simplemente muéstralo a tu jefe y dile que esto le permitirá vender el producto como una nueva versión con más escalabilidad incorporada :) Tus compañeros desarrolladores recibirán instrucciones para hacer esto todo el tiempo en el futuro, con suerte, y serás tenido en mayor consideración también.
Sí, también me topé con un problema con los objetos de conexión a una base de datos Oracle que no se eliminaba.
El anterior número de Mike Atlas es malo, pero al menos estaba claro sobre lo que estaba pasando mal. El problema con el que nos topamos fue que, de vez en cuando, bajo mucha carga, el sitio comenzaba a arrojar errores cuando intentábamos abrir una conexión, pero cuando miramos el sistema todo se había aclarado (porque el cobrador de garabe había despejado los objetos y liberado el grupo de conexión). Fue muy difícil de reproducir, hasta que estuve revisando el código y noté que una conexión no se cerraba en caso de error, cambiar esto a una declaración de using
corrigió todo el problema.
La respuesta breve es que si un objeto se toma el esfuerzo de implementar IDisposable, está ahí por alguna razón, por lo que SIEMPRE deseche cuando haya terminado, idealmente con una instrucción de using
. No seas astuto o tramposo con la eliminación a veces, pero no en otras ocasiones en las que no creas que debes bla, bla, bla. Solo haz lo que funciona todo el tiempo.
La respuesta más breve y más satisfactoria es que tienes razón, y tus compañeros de trabajo son idiotas que no saben lo que están haciendo.
Tuve un caso del que desafortunadamente no recuerdo los detalles, pero era un tipo de secuencias en capas. La secuencia de archivos de nivel inferior a veces se cerró antes de que se descargara el formateador de texto de nivel superior, lo que provocó que se perdiera la última salida escrita en el formateador de texto.
Sí, sí, sí , importa.
Recientemente he estado perfilando una aplicación que nunca se había perfilado. Es solo una aplicación de Winforms, no es gran cosa, ¿verdad?
Incorrecto.
Al no implementar identificadores de eventos IDisposible y no de referencia, la aplicación goteaba la memoria como un tamiz.
.NET Framework no lo absuelve de limpiar después de usted mismo, solo hace menos probable que rompa algo si no lo hace.
Dedique una hora, perfile su aplicación con ANTS Profiler . Es una prueba gratuita. Si no ve ninguna pérdida de memoria, continúe su camino. Si lo haces, es porque confiabas en .NET Framework para ser tu muleta.