Elimine objetos C♯ que devem implementar IDisposable, mas não

ATUALIZAÇÃO: Há uma implementação atualizada disso na última revisão do Gist . A nova implementação fornece delegação genérica (rápida), bem como reflexão (lenta).


Às vezes, ao usar a API de outra pessoa, você se depara com um tipo de lixo particularmente fedorento:

1. Um objeto aloca recursos não gerenciados.
2. O objeto fornece um método para desalocá-lo.
3. O objeto não implementa System.IDisposable .

Um exemplo desse antipadrão de software é a classe OpenNETCF.Phone.Sim.Sim . Sua documentação afirma: “Não é recomendável que você tenha mais de um objeto SIM aberto em seu aplicativo ao mesmo tempo.”

Este objeto prove um método Close , mas não implementa IDisposable . Se assim fosse, poderíamos arrumar escrevendo:

// Unfortunately, this isn't possible.
using (var sim = new OpenNETCF.Phone.Sim.Sim())
{
// Use the 'sim' variable ...
}

Mas, em vez disso, somos reduzidos a isso:

var sim = new OpenNETCF.Phone.Sim.Sim();
try
{
// Use the 'sim' variable ...
}
finally
{
sim
.Close();
}

Onde fica a pia? Eu preciso lavar minhas mãos!

Eu escrevi uma classe chamada Disposer <T> que torna a limpeza de lixo sujo uma experiência menos desagradável. Isso torna o bloco de uso útil para objetos como o Sim do OpenNETCF :

using (var disposer = new Disposer<OpenNETCF.Phone.Sim.Sim>(new OpenNETCF.Phone.Sim.Sim(), "Close"))
{
// Use the 'disposer.Object' property ...
}

Vejo? Suas mãos nem ficaram sujas.

Sob as cobertas, o Disposer <T> usa reflexão para chegar ao método Fechar do Sim . Certamente há uma penalidade de desempenho por usar reflexão. Se você está chamando o mesmo método de descarte muitas vezes, pode segurá-lo e passá-lo para o Disposer <T> :

// (Do this up front somewhere else.)
var closeMethod = typeof(OpenNETCF.Phone.Sim.Sim).GetMethod("Close");

// (Do this many times.)
using (var disposer = new Disposer<OpenNETCF.Phone.Sim.Sim>(OpenNETCF.Phone.Sim.Sim(), closeMethod))
{
// Use the 'disposer.Object' property ...
}

Escrevi este código em um modo de teste, então espero ter conseguido manter os bugs longe.

Fique saudável!

(Eu adaptei este protocolo de uma postagem do blog que escrevi em setembro de 2011.)