IDisposable & Resource Management
Dispose pattern, using/await using, finalizers e gerenciamento deterministico de recursos
Regra de ouro: O GC cuida de memoria gerenciada, mas nao libera recursos nao-gerenciados (files, sockets, handles OS, conexoes DB).
IDisposable expoe Dispose() para liberar esses recursos deterministicamente β sem esperar o GC. Ciclo de vida do objeto
IDisposable β por que existe?
O Garbage Collector libera memoria gerenciada automaticamente. Mas recursos do sistema operacional (file handles, sockets, conexoes de banco, mutexes) sao nao-gerenciados β o GC nao sabe libera-los. IDisposable.Dispose() e o contrato para cleanup deterministico.
| Aspecto | Recurso Gerenciado | Recurso Nao-Gerenciado |
|---|---|---|
| Exemplos | Objetos .NET, strings, arrays | File handles, sockets, DB connections, OS handles |
| Quem libera? | GC automaticamente | Voce via Dispose() |
| Quando libera? | Indeterminado (quando GC rodar) | Imediatamente no Dispose() |
| Consequencia do leak | Pressao de memoria (GC resolve) | Exaustao de recursos β file locks, connection pool esgotado |
GC Generations
| Generation | O que contem | Coleta |
|---|---|---|
| Gen 0 | Objetos recem-criados (efemeros) | Frequente e rapida |
| Gen 1 | Sobreviventes de Gen 0 | Menos frequente |
| Gen 2 | Objetos de vida longa | Rara e custosa (full GC) |
Finalizer promove o objeto para Gen 1+ β o GC precisa de pelo menos 2 coletas para liberar. Isso e caro. Por isso
GC.SuppressFinalize(this) e chamado em Dispose(): se voce ja limpou, nao precisa do finalizer. Finalizer vs Dispose?
Dispose() e chamado pelo desenvolvedor (ou via
using) β cleanup deterministico e imediato. Finalizer (~Type) e chamado pelo GC como backstop β nao-deterministico, lento, promove o objeto para Gen 1+. Na pratica: sempre chame Dispose(). Finalizer so existe como rede de seguranca caso alguem esqueca. Em codigo moderno, prefira SafeHandle que ja tem finalizacao critica embutida.