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.