c# - studio - ¿Eliminar() para limpiar los recursos gestionados?
returns c# (2)
En esta respuesta encontré,
Limpie los recursos no administrados en el método Finalize y los administrados en el método Dispose, cuando el patrón Dispose / Finalize se haya utilizado en su código.
Y más tarde encontré este buen artículo acerca de finalizar y disponer y tuve una idea clara acerca de ellos. El artículo tiene el siguiente código ( Página 3 ), para explicar los conceptos:
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Pero debajo de eso, aparece la misma nota (que incluí al principio de esta pregunta).
El patrón de disposición / finalización Microsoft recomienda que implemente tanto la distribución como la finalización cuando trabaje con recursos no administrados. La secuencia correcta sería, entonces, que un desarrollador llame a Dispose. La implementación de Finalize se ejecutaría y los recursos aún se liberarían cuando el objeto se recolecte como basura, incluso si un desarrollador no ha llamado explícitamente al método Dispose. Francesco Balena escribe en su blog "el patrón de Disposición / Finalización debe usarse solo cuando su tipo invoca código no administrado que asigna recursos no administrados (incluida la memoria no administrada) y devuelve un identificador que debe usar eventualmente para liberar el recurso. Ambos deben eliminarse y finalizarse encadenar a sus objetos padres llamando a los métodos respectivos de sus padres después de que hayan eliminado o finalizado sus propios miembros ". En pocas palabras, limpie los recursos no administrados en el método Finalizar y los administrados en el método Dispose, cuando el patrón Dispose / Finalize se haya utilizado en su código.
Ahora estoy confundido de nuevo. En el artículo completo y en el ejemplo de código, se muestra que los recursos no administrados deben liberarse en Dispose()
. Pero entonces, ¿cuál es la relevancia de ese comentario?
Editar:
Como se confirma que esta línea:
En pocas palabras, limpie los recursos no administrados en el método Finalizar y los administrados en el método Eliminar, cuando se haya utilizado el patrón Eliminar / Finalizar en su código
Es erróneo, edité esta respuesta .
Si un Foo
tiene recursos que se beneficiarán de una limpieza determinista, pero ninguno que pueda limpiarse de manera útil en un finalizador, debería implementarse como IDisposable
pero no debería anular Finalize
o tener un destructor. Si una clase tiene múltiples recursos, y al menos uno puede limpiarse en un finalizador, entonces cada recurso discreto que podría limpiarse en un finalizador debe encapsularse en su propio Finalizador / objeto equipado con destructor (que puede definirse en clase anidada protegida), y la clase que contendría esos recursos debería contener referencias a los objetos de envoltura. Una vez hecho esto, la clase externa ajustará el patrón para las clases con un método de Dispose
pero sin finalizador / destructor.
Ver es muy simple.
- Si está tratando con recursos no administrados , implemente tanto
Dispose
comoFinalize
.Dispose
debe ser llamado por los desarrolladores para liberar los recursos tan pronto como vean que ya no es necesario para ellos. Si se olvidan de llamar aDispose
, Framework llama a finalizar en su propio ciclo de GC (normalmente tomará su propio tiempo). - Si NO está tratando con recursos no administrados , entonces no haga nada. No implementar
Finalize
niDispose
. - Si su objeto utiliza objetos desechables internamente : usted implementa
Dispose()
si creó y conservó una referencia a cualquier objeto de un tipo que implementaDispose()
y que aún no haya eliminado.
Algunos ejemplos clásicos:
System.IO.FileStream
objeto System.IO.FileStream
administra los manejadores de bloqueo / flujo a los archivos. Así se implementa tanto disponer como finalizar. Si el desarrollador lo desecha, el otro programa puede acceder a él de inmediato. Si se olvida de desecharla, Framework la finaliza y cierra los manejadores más adelante en su ciclo de GC.
System.Text.StringBuilder
dosis de System.Text.StringBuilder
no tiene ningún recurso no administrado. Así que no disponemos ni finalizamos.
En cuanto al patrón se refiere a lo que significa
// Code to dispose the managed resources of the class
es que llame a los métodos Dispose de cualquier objeto .NET que tenga como componentes dentro de esa clase
Y
// Code to dispose the un-managed resources of the class
Medios para cerrar las asas en bruto y los punteros. Aquí está su código actualizado con ejemplos
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
internalComponent1.Dispose();
internalComponent2.Dispose();
}
// Code to dispose the un-managed resources of the class
CloseHandle(handle);
handle = IntPtr.Zero;
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Aquí hay una vieja pregunta que lo explica.