Ao utilizar recursos não gerenciados, em .NET, precisamos garantir que estes sejam devidamente liberados. Para isso, quando criamos classes que alocam tais recursos, implementamos a interface IDisposable. Caberá ao programador que consome essa classe chamar o método Dispose que irá liberar tais recursos.
Infelizmente, muitas vezes, os programadores que consomem classes que alocam recursos não gerenciados esquecem de chamar o método Dispose. Assim, alguns recursos não gerenciados acabam pendurados por nossa aplicação gerando erros difíceis de identificar e corrigir. Uma abordagem interessante para minimizar esse risco é implementada a seguir:
using System;
using static System.Console;
class Program
{
static void Main(string[] args)
{
var n = new DisposableObject();
n.SayHello();
//n.Dispose();
WriteLine("Done!");
}
}
class DisposableObject : IDisposable
{
public void SayHello() => WriteLine("Hello!");
~DisposableObject() =>
throw new InvalidOperationException($"{nameof(DisposableObject)}.{nameof(Dispose)}() not called.");
public void Dispose()
{
GC.SuppressFinalize(this);
WriteLine("Dispose was called.");
}
}
Aqui, o destrutor irá lançar uma exception sempre que evocado. O destrutor, por padrão, é chamado pelo Garbage Collector no momento que o objeto está sendo retirado da memória. O que fizemos é desativar essa chamada quando o método Dispose é acionado. Dessa forma, a exceção será lançada apenas se o método Dispose não for chamado.

