Buscar..


Observaciones

  • IDisposable de los clientes de la clase que implementan IDisposable asegurarse de que llamen al método Dispose cuando hayan terminado de usar el objeto. No hay nada en el CLR que busque directamente los objetos para invocar un método Dispose .

  • No es necesario implementar un finalizador si su objeto solo contiene recursos administrados. Asegúrese de llamar a Dispose en todos los objetos que usa su clase cuando implemente su propio método Dispose .

  • Se recomienda hacer que la clase sea segura contra múltiples llamadas a Dispose , aunque lo ideal sería que solo se llame una vez. Esto se puede lograr agregando una variable private bool a su clase y estableciendo el valor en true cuando se haya ejecutado el método Dispose .

En una clase que contiene solo recursos gestionados

Los recursos administrados son recursos que el recolector de basura del tiempo de ejecución conoce y tiene bajo control. Hay muchas clases disponibles en el BCL, por ejemplo, como una SqlConnection que es una clase de contenedor para un recurso no administrado. Estas clases ya implementan la interfaz IDisposable : depende de su código limpiarlas cuando haya terminado.

No es necesario implementar un finalizador si su clase solo contiene recursos administrados.

public class ObjectWithManagedResourcesOnly : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();

    public void Dispose()
    {
        sqlConnection.Dispose();
    }
}

En una clase con recursos gestionados y no gestionados.

Es importante dejar que la finalización ignore los recursos administrados. El finalizador se ejecuta en otro subproceso: es posible que los objetos gestionados ya no existan en el momento en que se ejecuta el finalizador. La implementación de un método protegido de Dispose(bool) es una práctica común para garantizar que los recursos administrados no tengan su método Dispose llamado desde un finalizador.

public class ManagedAndUnmanagedObject : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();
    private UnmanagedHandle unmanagedHandle = Win32.SomeUnmanagedResource();
    private bool disposed;

    public void Dispose()
    {
        Dispose(true); // client called dispose
        GC.SuppressFinalize(this); // tell the GC to not execute the Finalizer
    }

    protected virtual void Dispose(bool disposeManaged)
    {
        if (!disposed)
        {
            if (disposeManaged)
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Dispose();
                }
            }

            unmanagedHandle.Release();

            disposed = true;
        }
    }

    ~ManagedAndUnmanagedObject()
    {
        Dispose(false);
    }
}

IDisponible, Disponer

.NET Framework define una interfaz para los tipos que requieren un método de desmontaje:

public interface IDisposable
{
  void Dispose();
}

Dispose() se usa principalmente para limpiar recursos, como referencias no administradas. Sin embargo, también puede ser útil forzar la disposición de otros recursos incluso si se administran. En lugar de esperar a que el GC finalmente limpie también la conexión de su base de datos, puede asegurarse de que se haga en su propia implementación de Dispose() .

public void Dispose()
{
   if (null != this.CurrentDatabaseConnection)
   {
       this.CurrentDatabaseConnection.Dispose();
       this.CurrentDatabaseConnection = null;
   }
}

Cuando necesite acceder directamente a recursos no administrados, como punteros no administrados o recursos win32, cree una clase SafeHandle de SafeHandle y use las convenciones / herramientas de esa clase para hacerlo.

En una clase heredada con recursos gestionados

Es bastante común que pueda crear una clase que implemente IDisposable , y luego derivar clases que también contengan recursos administrados. Se recomienda marcar el método de Dispose con la palabra clave virtual para que los clientes puedan limpiar los recursos que posean.

public class Parent : IDisposable
{
    private ManagedResource parentManagedResource = new ManagedResource();

    public virtual void Dispose()
    {
        if (parentManagedResource != null)
        {
            parentManagedResource.Dispose();
        }
    }
}

public class Child : Parent
{
    private ManagedResource childManagedResource = new ManagedResource();

    public override void Dispose()
    {
        if (childManagedResource != null)
        {
            childManagedResource.Dispose();
        }
        //clean up the parent's resources
        base.Dispose();
    }
}

usando palabras clave

Cuando un objeto implementa la interfaz IDisposable , se puede crear dentro de la sintaxis de using :

using (var foo = new Foo())
{
    // do foo stuff
} // when it reaches here foo.Dispose() will get called

public class Foo : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("dispose called");
    }
}

Ver demo

using azúcar sintáctica es para un bloque try/finally ; el uso anterior se traduciría aproximadamente en:

{
    var foo = new Foo();
    try
    {
        // do foo stuff
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow