C# Memória Avançado
using e IDisposable
Em C#, o gerenciamento de memória é automático para objetos gerenciados, mas recursos não gerenciados (como arquivos, conexões de rede ou ponteiros) precisam ser liberados explicitamente. A interface IDisposable define o método Dispose() para essa finalidade. A instrução using garante que Dispose() seja chamado mesmo se ocorrer uma exceção, evitando vazamentos de recursos.
O padrão using pode ser aplicado de duas formas: a declaração using (a partir do C# 8) e o bloco using. Ambos garantem a chamada a Dispose() ao final do escopo. Além disso, ao implementar IDisposable em classes próprias, é recomendável seguir o Dispose pattern, que inclui um método protected virtual void Dispose(bool disposing) para lidar com recursos gerenciados e não gerenciados, e um finalizador (~Destructor) para liberar recursos não gerenciados caso o usuário esqueça de chamar Dispose().
Neste card, vamos explorar como usar using com recursos que implementam IDisposable, como implementar corretamente o Dispose pattern e por que isso é crucial para a robustez de aplicações que interagem com o sistema operacional.
Pontos-chave
IDisposabledefine o métodoDispose()para liberar recursos não gerenciados.- A declaração
using(C# 8+) ou o blocousinggarantem a chamada aDispose()mesmo com exceções. - O Dispose pattern completo inclui
Dispose(bool)e um finalizador para recursos não gerenciados. - Sempre chame
GC.SuppressFinalize(this)noDispose()para evitar finalização desnecessária. - Objetos
IDisposabledevem ser descartados o mais rápido possível após o uso.
using System;
using System.IO;
public class ResourceHolder : IDisposable
{
private FileStream _fileStream;
private bool _disposed = false;
public ResourceHolder(string path)
{
_fileStream = new FileStream(path, FileMode.OpenOrCreate);
}
public void WriteData(byte[] data)
{
if (_disposed) throw new ObjectDisposedException(nameof(ResourceHolder));
_fileStream.Write(data, 0, data.Length);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_fileStream?.Dispose();
}
_disposed = true;
}
~ResourceHolder()
{
Dispose(false);
}
}
class Program
{
static void Main()
{
using (var holder = new ResourceHolder("test.txt"))
{
holder.WriteData(new byte[] { 1, 2, 3 });
} // Dispose é chamado automaticamente aqui
Console.WriteLine("Recurso liberado.");
}
}