Menu
Coddy logo textTech

IDisposable y la sentencia using

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 45 de 70.

Algunos objetos conservan recursos que el recolector de basura no puede limpiar automáticamente: identificadores de archivo, conexiones de base de datos y sockets de red. La interfaz IDisposable proporciona una forma estándar de liberar estos recursos cuando hayas terminado de usarlos.

Una clase implementa IDisposable proporcionando un método Dispose():

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

Podrías llamar a Dispose() manualmente, pero ¿qué ocurre si se produce una excepción antes de llegar a esa línea? La instrucción using garantiza que la limpieza se realice, incluso cuando algo sale mal:

using (FileHandler handler = new FileHandler())
{
    // Trabajar con el handler
}  // Dispose() se llama automáticamente aquí

El C# moderno ofrece una sintaxis más limpia con la declaración using, que elimina el objeto cuando sale del ámbito:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Trabajar con handler
}  // Dispose() se llama cuando el método sale

La instrucción using funciona con cualquier tipo que implemente IDisposable. Las clases integradas como StreamReader, SqlConnection y HttpClient implementan esta interfaz, lo que hace que la gestión adecuada de recursos sea sencilla y fiable.

challenge icon

Desafío

Fácil

Construyamos un simulador de conexión a una base de datos que demuestre una gestión adecuada de los recursos mediante la interfaz IDisposable y la instrucción using. Crearás una clase que registre cuándo se abren y se cierran las conexiones, garantizando que los recursos se liberen siempre correctamente.

Organizarás tu código en dos archivos:

  • DatabaseConnection.cs: Crea una clase DatabaseConnection en el espacio de nombres DataAccess que implemente IDisposable. Tu conexión debe:
    • Tener una propiedad ConnectionName (de tipo string y de solo lectura) establecida mediante el constructor
    • Registrar si la conexión se ha liberado mediante un campo booleano privado
    • Imprimir Connection opened: {ConnectionName} cuando se cree el objeto (en el constructor)
    • Implementar el método Dispose() para imprimir Connection closed: {ConnectionName}, pero solo si aún no se ha liberado (para evitar una liberación doble)
    • Tener un método Query(string sql) que devuelva Executing on {ConnectionName}: {sql}
  • Program.cs: En tu archivo principal, demuestra una gestión adecuada de los recursos utilizando la instrucción using con tu conexión a la base de datos. Crea una conexión, ejecuta una consulta y deja que el bloque using gestione automáticamente la limpieza.

Recibirás dos entradas:

  • El nombre de la conexión (por ejemplo, MainDB)
  • La consulta SQL que se ejecutará (por ejemplo, SELECT * FROM Users)

Usa una instrucción using para crear la conexión. Dentro del bloque, llama al método Query e imprime su resultado. Cuando termine el bloque using, Dispose() se llamará automáticamente.

Por ejemplo, si las entradas son MainDB y SELECT * FROM Users, la salida debería ser:

Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDB

Observa cómo la conexión se cierra automáticamente cuando termina el bloque using: nunca tienes que acordarte de llamar manualmente a Dispose(). ¡Este patrón garantiza que los recursos se limpien siempre, incluso si se produce una excepción dentro del bloque!

Pruébalo tú mismo

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO: Usa una sentencia 'using' para crear un DatabaseConnection
        // Dentro del bloque using:
        // 1. Llama al método Query con el sqlQuery
        // 2. Imprime el resultado del método Query
        // El método Dispose se llamará automáticamente cuando termine el bloque using
        
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C# online