Como implementar correctamente IDisposable…

Primero lo primero… La interface IDisposable define un método “personalizado” para liberar los recursos administrados y no administrados.
IDisposable se usa principalmente para liberar los recursos no administrados, ya que el recolector de elementos no utilizados (GC: Garbage Collector) libera automáticamente la memoria asignada a un objeto administrado cuando ya no se utiliza, pero no se puede prever cuándo se producirá la recolección de elementos no utilizados. Además, el GC no reconoce recursos no administrados, como ser objetos de tipos File y Font.

A continuación, les muestro el código de ejemplo y aclaraciones sobre la implementación de una clase IDisposable:

public class ClaseDisposable : IDisposable {
    // Recursos manejados
    private Component componentes = new Component();
    private DataSet dataSetDisposable = new DataSet();

    // Indica si ya se llamo al método Dispose. (default = false)
    private Boolean disposed;

    /// <summary>
    /// Implementación de IDisposable. No se sobreescribe.
    /// </summary>
    public void Dispose() {
        this.Dispose(true);
        // GC.SupressFinalize quita de la cola de finalización al objeto.
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Limpia los recursos manejados y no manejados.
    /// </summary>
    /// <param name="disposing">
    /// Si es true, el método es llamado directamente o indirectamente
    /// desde el código del usuario.
    /// Si es false, el método es llamado por el finalizador
    /// y sólo los recursos no manejados son finalizados.
    /// </param>
    protected virtual void Dispose(bool disposing) {
        // Preguntamos si Dispose ya fue llamado.
        if (!this.disposed) {
            if (disposing) {
                // Llamamos al Dispose de todos los RECURSOS MANEJADOS.
                this.componentes.Dispose();
                this.dataSetDisposable.Dispose();
            }

            // Acá finalizamos correctamente los RECURSOS NO MANEJADOS
            // ...

        }
        this.disposed = true;
    }

    /// <summary>
    /// Destructor de la instancia
    /// </summary>
    ~ClaseDisposable() {
        this.Dispose(false);
    }
}

Podemos agregar que el método Dispose(bool disposing) es virtual, por lo que podemos redefinirlo en clases que hereden de esta, por lo cual en dichas clases no necesitamos implementar nuevamente IDisposable. Un ejemplo de este comportamiento es un Formulario que hereda (obviamente) de Form, como vemos a continuación, en Designer tenemos el siguiente código:

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
     if (disposing && (components != null)) {
          components.Dispose();
     }
     base.Dispose(disposing);
}

También podemos ver como sería la llamada a Dispose. Hay dos tipos de llamadas, la directa y la indirecta:
Llamada Directa:

ClaseDisposable objetoDisposable = new ClaseDisposable();
// utilizamos el objetoDisposable
// ...
// y lo finalizamos:
objetoDisposable.Dispose();

Llamada Indirecta:

using (ClaseDisposable objetoDisposable = new ClaseDisposable()) {
    // utilizamos el objetoDisposable
    // ...
}
//se finaliza automáticamente al salir del using

Más información sobre using…

Espero que les sea útil.
(FxCop nos sugiere la implementación de IDisposable de esta manera cuando nuestra clase trabaja con recursos administrados y que implementan el método Dispose… Es bueno hacerle caso, implementando IDisposable como corresponde 😀 )

Anuncios
Publicado en C#, Tips. Etiquetas: . Leave a Comment »

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: