¿Cuándo implementaría IDispose en una clase en lugar de un destructor? Leí este artículo , pero todavía me pierdo el punto.
Mi suposición es que si implemento IDispose en un objeto, puedo 'destruirlo' explícitamente en lugar de esperar a que el recolector de basura lo haga. ¿Es esto correcto?
¿Eso significa que siempre debería llamar explícitamente a Dispose en un objeto? ¿Cuáles son algunos ejemplos comunes de esto?
c#
.net
dispose
destructor
Jordan Parmer
fuente
fuente
using
construcción.Respuestas:
Un finalizador (también conocido como destructor) es parte de la recolección de basura (GC); es indeterminado cuando (o incluso si) esto sucede, ya que GC ocurre principalmente como resultado de la presión de la memoria (es decir, necesita más espacio). Los finalizadores generalmente solo se usan para limpiar recursos no administrados , ya que los recursos administrados tendrán su propia recolección / eliminación.
Por tanto,
IDisposable
se utiliza para limpiar de forma determinista los objetos, es decir, ahora. No recopila la memoria del objeto (que todavía pertenece a GC), pero se usa, por ejemplo, para cerrar archivos, conexiones de bases de datos, etc.Hay muchos temas anteriores sobre esto:
Finalmente, tenga en cuenta que no es raro que un
IDisposable
objeto también tenga un finalizador; en este caso,Dispose()
normalmente llamaGC.SuppressFinalize(this)
, lo que significa que GC no ejecuta el finalizador, simplemente tira la memoria (mucho más barato). El finalizador aún se ejecuta si se olvidaDispose()
del objeto.fuente
La función del
Finalize()
método es garantizar que un objeto .NET pueda limpiar los recursos no administrados cuando se recolecta la basura . Sin embargo, los objetos como las conexiones de bases de datos o los controladores de archivos deben liberarse lo antes posible, en lugar de depender de la recolección de basura. Para eso, debe implementar laIDisposable
interfaz y liberar sus recursos en elDispose()
método.fuente
Hay una muy buena descripción en MSDN :
fuente
Lo único que debería estar en un destructor de C # es esta línea:
Eso es. Nada más debería estar en ese método.
fuente
Su pregunta sobre si debe llamar siempre o no
Dispose
suele ser un debate acalorado. Consulte este blog para obtener una perspectiva interesante de personas respetadas en la comunidad .NET.Personalmente, creo que la posición de Jeffrey Richter de que llamar
Dispose
no es obligatorio es increíblemente débil. Da dos ejemplos para justificar su opinión.En el primer ejemplo, dice que llamar
Dispose
a los controles de Windows Forms es tedioso e innecesario en los escenarios principales. Sin embargo, no menciona que, enDispose
realidad, los contenedores de control lo llaman automáticamente en esos escenarios convencionales.En el segundo ejemplo, afirma que un desarrollador puede asumir incorrectamente que la instancia de
IAsyncResult.WaitHandle
debe eliminarse de forma agresiva sin darse cuenta de que la propiedad inicializa perezosamente el identificador de espera, lo que genera una penalización de rendimiento innecesaria. Pero, el problema con este ejemplo es que elIAsyncResult
mismo no se adhiere a las pautas publicadas por Microsoft para tratar conIDisposable
objetos. Es decir, si una clase tiene una referencia a unIDisposable
tipo, la clase misma debería implementarlaIDisposable
. Si seIAsyncResult
sigue esa regla, entonces su propioDispose
método podría tomar la decisión sobre cuál de sus miembros constituyentes necesita eliminarse.Entonces, a menos que alguien tenga un argumento más convincente, me quedaré en el campo de "siempre llamar a Dispose" con el entendimiento de que habrá algunos casos marginales que surjan principalmente de malas elecciones de diseño.
fuente
Realmente es bastante simple. Sé que ha sido respondida, pero intentaré de nuevo, pero intentaré que sea lo más simple posible.
Por lo general, nunca se debe utilizar un destructor. Solo se ejecuta .net quiere que se ejecute. Solo se ejecutará después de un ciclo de recolección de basura. Es posible que nunca se ejecute durante el ciclo de vida de su aplicación. Por esta razón, nunca debe poner ningún código en un destructor que 'deba' ejecutarse. Tampoco puede confiar en que exista ningún objeto existente dentro de la clase cuando se ejecuta (es posible que ya se hayan limpiado ya que el orden en el que se ejecutan los destructores no está garantizado).
IDisposible debe usarse siempre que tenga un objeto que cree recursos que necesiten limpieza (es decir, identificadores de archivos y gráficos). De hecho, muchos argumentan que cualquier cosa que coloque en un destructor debería colocarse en IDisposable debido a las razones enumeradas anteriormente.
La mayoría de las clases llamarán a dispose cuando se ejecute el finalizador, pero esto simplemente está ahí como una protección y nunca se debe confiar en él. Debe desechar explícitamente todo lo que implemente IDisposable cuando haya terminado con él. Si implementa IDisposable, debe llamar a dispose en finalizer. Ver http://msdn.microsoft.com/en-us/library/system.idisposable.aspx para ver un ejemplo.
fuente
Aquí hay otro buen artículo que aclara parte de la niebla que rodea a IDisposable, GC y desechar.
Chris Lyons WebLog Desmitificando Dispose
fuente