Menu
Coddy logo textTech

IDisposable e a Instrução using

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 45 de 70.

Alguns objetos mantêm recursos que o garbage collector não consegue limpar automaticamente - manipuladores de arquivos, conexões de banco de dados, sockets de rede. A interface IDisposable fornece uma maneira padrão de liberar esses recursos quando você terminar de usá-los.

Uma classe implementa IDisposable ao fornecer um método Dispose():

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

Você poderia chamar Dispose() manualmente, mas e se uma exceção ocorrer antes de você chegar a essa linha? A instrução using garante que a limpeza ocorra, mesmo quando as coisas dão errado:

using (FileHandler handler = new FileHandler())
{
    // Trabalhe com o manipulador
}  // Dispose() chamado automaticamente aqui

O C# moderno oferece uma sintaxe mais limpa com a declaração using, que descarta o objeto quando ele sai de escopo:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Trabalhar com o handler
}  // Dispose() é chamado quando o método termina

A instrução using funciona com qualquer tipo que implementa IDisposable. Classes integradas como StreamReader, SqlConnection e HttpClient todas implementam essa interface, tornando o gerenciamento de recursos adequado simples e confiável.

challenge icon

Desafio

Fácil

Vamos construir um simulador de conexão de banco de dados que demonstra o gerenciamento adequado de recursos usando a interface IDisposable e a instrução using. Você criará uma classe que rastreia quando as conexões são abertas e fechadas, garantindo que os recursos sejam sempre liberados corretamente.

Você organizará seu código em dois arquivos:

  • DatabaseConnection.cs: Crie uma classe DatabaseConnection no namespace DataAccess que implementa IDisposable. Sua conexão deve:
    • Ter uma propriedade ConnectionName (string, somente leitura) definida através do construtor
    • Rastrear se a conexão foi descartada usando um campo booleano privado
    • Imprimir Connection opened: {ConnectionName} quando o objeto for criado (no construtor)
    • Implementar o método Dispose() para imprimir Connection closed: {ConnectionName} - mas apenas se ainda não tiver sido descartado (evitando o descarte duplo)
    • Ter um método Query(string sql) que retorna Executing on {ConnectionName}: {sql}
  • Program.cs: Em seu arquivo principal, demonstre o gerenciamento adequado de recursos usando a instrução using com sua conexão de banco de dados. Crie uma conexão, execute uma consulta e deixe o bloco using cuidar da limpeza automaticamente.

Você receberá duas entradas:

  • O nome da conexão (ex: MainDB)
  • A consulta SQL a ser executada (ex: SELECT * FROM Users)

Use uma instrução using para criar sua conexão. Dentro do bloco, chame o método Query e imprima seu resultado. Quando o bloco using terminar, o Dispose() será chamado automaticamente.

Por exemplo, se as entradas forem MainDB e SELECT * FROM Users, a saída deve ser:

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

Observe como a conexão é fechada automaticamente quando o bloco using termina - você nunca precisa se lembrar de chamar Dispose() manualmente. Esse padrão garante que os recursos sejam sempre limpos, mesmo que ocorra uma exceção dentro do bloco!

Folha de consulta

A interface IDisposable fornece uma maneira padrão de liberar recursos que o coletor de lixo não pode limpar automaticamente (manipuladores de arquivos, conexões de banco de dados, sockets de rede).

Uma classe implementa IDisposable fornecendo um método Dispose():

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

A instrução using garante que a limpeza ocorra automaticamente, mesmo quando ocorrem exceções:

using (FileHandler handler = new FileHandler())
{
    // Trabalha com o handler
}  // Dispose() chamado automaticamente aqui

O C# moderno oferece uma sintaxe mais limpa com a declaração using:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Trabalha com o handler
}  // Dispose() chamado quando o método termina

A instrução using funciona com qualquer tipo que implemente IDisposable, incluindo classes integradas como StreamReader, SqlConnection e HttpClient.

Experimente você mesmo

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO: Use uma instrução 'using' para criar uma DatabaseConnection
        // Dentro do bloco using:
        // 1. Chame o método Query com o sqlQuery
        // 2. Imprima o resultado do método Query
        // O método Dispose será chamado automaticamente quando o bloco using terminar
        
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos