Sobes.tech
Middle

Qual é a diferença entre os métodos Dispose e Finalize?

sobes.tech IA

Resposta da IA

O Dispose é chamado explicitamente pelo desenvolvedor ou pelo ambiente de execução (por exemplo, using) para libertar recursos não geridos. Finalize (através do destruidor em C#) é chamado pelo recolhedor de lixo ao destruir o objeto, se este não tiver sido libertado explicitamente.

Critério Dispose Finalize (através do destruidor)
Chamada Especificada explicitamente pelo desenvolvedor (using, Dispose()) Automática pelo recolhedor de lixo
Tempo de execução Determinista Não determinista (depende do recolhedor de lixo)
Propósito Libertar recursos geridos e não geridos Libertar apenas recursos não geridos
Implementação Interface IDisposable Sobrescrever o método Object.Finalize (através do destruidor)
Uso Método preferido para libertar recursos Mecanismo de reserva para recursos não geridos

Exemplo de uso de using (chamada automática a Dispose):

// Exemplo de uso de uma classe que implementa IDisposable
using (var fileStream = new System.IO.FileStream("myfile.txt", System.IO.FileMode.Open))
{
    // Trabalhar com o ficheiro
} // Aqui, fileStream.Dispose() é chamado automaticamente

Exemplo de classe com IDisposable e destruidor:

using System;

public class MyDisposableClass : IDisposable
{
    private IntPtr unmanagedResource; // Representa um recurso não gerido
    private bool disposed = false;

    public MyDisposableClass()
    {
        // Inicialização do recurso não gerido
        unmanagedResource = System.Runtime.InteropServices.Marshal.AllocHGlobal(100);
        Console.WriteLine("Recurso alocado.");
    }

    // Implementação de IDisposable
    public void Dispose()
    {
        Dispose(true);
        // Suprimir finalização, pois o recurso já foi libertado
        GC.SuppressFinalize(this);
        Console.WriteLine("Dispose() chamado.");
    }

    // Método protegido virtual para libertar recursos
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Libertar recursos geridos (se houver)
                Console.WriteLine("Libertar recursos geridos.");
            }

            // Libertar recursos não geridos
            if (unmanagedResource != IntPtr.Zero)
            {
                System.Runtime.InteropServices.Marshal.FreeHGlobal(unmanagedResource);
                unmanagedResource = IntPtr.Zero;
                Console.WriteLine("Recurso não gerido libertado.");
            }

            disposed = true;
        }
    }

    // Destruidor (finalizador)
    ~MyDisposableClass()
    {
        Dispose(false); // Libertar apenas recursos não geridos
        Console.WriteLine("Finalizador chamado.");
    }
}

O método Dispose deve ser implementado em todas as classes que gerem recursos não geridos (ficheiros, ligações de rede, descritores, etc.). Finalize deve ser usado como uma opção de reserva para libertar esses recursos caso Dispose não tenha sido chamado. As classes que implementam Finalize devem suprimir a sua chamada em Dispose(true) para evitar libertar os recursos duas vezes.