2009-03-05 20 views
17

Si .NET tiene una recolección de basura, ¿por qué tiene que llamar explícitamente al IDisposable?¿Para qué es IDisposable?

+2

Existen muchas respuestas a esta pregunta si coloca IDisposable en el cuadro de búsqueda. –

Respuesta

46

La recolección de basura es para la memoria. Debe deshacerse de los recursos que no son de memoria: identificadores de archivos, sockets, identificadores GDI +, conexiones de bases de datos, etc. Normalmente, eso es lo que subyace a un tipo IDisposable, aunque el identificador real puede ser bastante largo en una cadena de referencias. Por ejemplo, puede Dispose un XmlWriter que dispone de un StreamWriter al que hace referencia, que dispone del FileStreamal que tiene referencia, que libera el identificador del archivo.

5

Porque los objetos alguna vez tienen recursos al lado de la memoria. GC libera la memoria; IDisposable es para que pueda lanzar cualquier otra cosa.

1

porque desea controlar cuándo se limpiarán los recursos que posee su objeto.

Mira, GC funciona, pero lo hace cuando se siente así, e incluso entonces, los finalizadores que agregue a sus objetos recibirán llamadas solo después de 2 recolecciones de GC. A veces, quieres limpiar esos objetos inmediatamente.

Esto es cuando IDisposable se utiliza. Llamando a Dispose() explícitamente (o usando el azúcar sintáctico de un bloque de uso) puede acceder a su objeto para limpiarse de una manera estándar (es decir, podría haber implementado su propia llamada de limpieza() y haberlo llamado explícitamente en su lugar)

Los recursos de ejemplo que desea limpiar inmediatamente son: identificadores de bases de datos, manejadores de archivos, identificadores de red.

8

Ampliando un poco en otros comentarios:

El método Dispose() se recurrirá a todos los objetos que tienen referencias a los recursos gestionados de la ONU. Ejemplos de esto incluirían flujos de archivos, conexiones de bases de datos, etc. Una regla básica que funciona la mayor parte del tiempo es: "si el objeto .NET implementa IDisposable, debe llamar a Dispose() cuando haya terminado con el objeto.

sin embargo, algunas otras cosas a tener en cuenta:.

  • Calling disponer no le da el control sobre cuando el objeto es en realidad destruye y libera la memoria de GC se encarga de que para nosotros y lo hace mejor que podamos
  • . Dispose limpia todos los recursos nativos, a lo largo de la pila de clases base como Jon indicó. Luego llama a SuprimirFinalizar() para indicar que el objeto está listo para ser reclamado y no se necesita más trabajo. La próxima ejecución del GC lo limpiará.
  • Si no se llama a Dispose, GC considera que el objeto necesita limpieza, pero debe llamarse a Finalize primero, para asegurarse de que se liberan los recursos, la solicitud de Finalize se pone en cola y el GC se mueve, por lo que La falta de una llamada a Dispose hace que se ejecute un GC más antes de poder limpiar el objeto. Esto hace que el objeto sea promovido a la siguiente "generación" de GC. Esto puede no parecer un gran problema, pero en una aplicación con memoria presionada, la promoción de objetos hasta generaciones más altas de GC puede empujar una aplicación de memoria alta a través de la pared a una aplicación sin memoria.
  • No implemente IDisposable en sus propios objetos a menos que sea absolutamente necesario. Las implementaciones mal implementadas o innecesarias en realidad pueden empeorar las cosas en lugar de mejorarlas.Una buena orientación se puede encontrar aquí:

    Implementing a Dispose Method

    Or read that whole section of MSDN on Garbage Collection

+0

Asunto: "No implemente IDisposable ... a menos que sea absolutamente necesario" -simplemente tenga cuidado al definir las interfaces -si hay alguna posibilidad de que una implementación de la interfaz requiera su eliminación, entonces la interfaz debe ser identificable desde el principio. De lo contrario, todos los clientes necesitarán refactorización. – morechilli

+0

+1 para una respuesta buena y más completa. Sospecho que la advertencia sobre no implementar algo a menos que sea necesario se dirige más a 'Finalizar()' que a 'Dispose() '. –

+0

El objetivo de "IDisposable" es proporcionar un medio estándar para informar a los objetos cuando sus servicios ya no son necesarios. Esto, a su vez, les permite notificar a otros objetos cuyos servicios han estado usando que los servicios de esos otros objetos ya no son necesarios. Los objetos que se preocupan cuando sus servicios ya no son necesarios deberían implementar 'IDisposable'. Los objetos que poseen otros objetos que se preocupan cuando ya no son necesarios también deben implementar 'IDisposable', por lo que pueden reenviar notificaciones" ya no necesarias "a esos objetos internos. – supercat

0

La interfaz IDisposable a menudo se describe en términos de recursos, pero la mayoría de estas descripciones no consideran realmente lo que realmente significa el "recurso".

Algunos objetos necesitan solicitar a entidades externas que hagan algo en su nombre, en detrimento de otras entidades, hasta nuevo aviso. Por ejemplo, un objeto que abarca una secuencia de archivos puede necesitar pedirle a un sistema de archivos (que puede estar en cualquier parte del universo conectado) que otorgue acceso exclusivo a un archivo. En muchos casos, la necesidad del objeto para la entidad externa estará ligada a la necesidad del código externo para el objeto. Una vez que el código del cliente haya hecho todo lo que va a hacer con el objeto de flujo de archivos anteriormente mencionado, por ejemplo, ese objeto ya no necesitará tener acceso exclusivo (o cualquier acceso para el caso) a su archivo asociado.

En general, un objeto X que le pide a una entidad que haga algo hasta nuevo aviso incurre en la obligación de entregar dicho aviso, pero no puede entregar dicho aviso siempre que el cliente de X necesite los servicios de X. El objetivo de IDisposable es proporcionar una forma uniforme de informar a los objetos que sus servicios ya no serán necesarios, para que puedan notificar a las entidades (si las hay) que actuaban en su nombre que sus servicios ya no son necesarios. El código que llama al IDisposable no necesita conocer ni preocuparse por los servicios (si los hay) que un objeto ha solicitado a entidades externas, ya que IDisposable simplemente invita a un objeto a cumplir obligaciones (si las hay) con entidades externas.

Para poner cosas en términos de "recursos", un objeto adquiere un recurso cuando le pide a una entidad externa que haga algo en su nombre (normalmente, aunque no necesariamente, otorgando el uso exclusivo de algo) hasta nuevo aviso, y libera un recurso cuando dice que la entidad externa sus servicios ya no son necesarios. El código que adquiere un recurso no gana una "cosa" tanto como incurre en una obligación; liberar un recurso no renuncia a una "cosa", sino que cumple una obligación.

Cuestiones relacionadas