Quando eu implementaria IDispose em uma classe em oposição a um destruidor? Eu li este artigo , mas ainda estou perdendo o ponto.
Minha suposição é que se eu implementar IDispose em um objeto, posso explicitamente 'destruí-lo' em vez de esperar que o coletor de lixo faça isso. Isso está correto?
Isso significa que sempre devo chamar explicitamente Dispose em um objeto? Quais são alguns exemplos comuns disso?
c#
.net
dispose
destructor
Jordan Parmer
fonte
fonte
using
construção.Respostas:
Um finalizador (também conhecido como destruidor) faz parte da coleta de lixo (GC) - é indeterminado quando (ou mesmo se) isso acontece, pois o GC ocorre principalmente como resultado da pressão da memória (ou seja, precisa de mais espaço). Os finalizadores geralmente são usados apenas para limpar recursos não gerenciados , uma vez que os recursos gerenciados terão sua própria coleção / descarte.
Portanto,
IDisposable
é usado para limpar objetos de forma determinística , ou seja, agora. Não coleta a memória do objeto (que ainda pertence ao GC) - mas é usado, por exemplo, para fechar arquivos, conexões de banco de dados, etc.Existem muitos tópicos anteriores sobre isso:
Por fim, observe que não é incomum que um
IDisposable
objeto também tenha um finalizador; neste caso,Dispose()
geralmente chamaGC.SuppressFinalize(this)
, o que significa que o GC não executa o finalizador - ele simplesmente joga a memória fora (muito mais barato). O finalizador ainda será executado se você esquecerDispose()
o objeto.fonte
A função do
Finalize()
método é garantir que um objeto .NET possa limpar recursos não gerenciados quando o lixo for coletado . No entanto, objetos como conexões de banco de dados ou manipuladores de arquivos devem ser liberados o mais rápido possível, em vez de depender da coleta de lixo. Para isso você deve implementarIDisposable
interface e liberar seus recursos noDispose()
método.fonte
Há uma descrição muito boa no MSDN :
fonte
A única coisa que deve estar em um destruidor C # é esta linha:
É isso aí. Nada mais deveria estar nesse método.
fonte
Sua pergunta sobre se você deve sempre ligar ou não
Dispose
é geralmente um debate acalorado. Veja este blog para uma perspectiva interessante de indivíduos respeitados na comunidade .NET.Pessoalmente, acho que a posição de Jeffrey Richter de que pagar
Dispose
não é obrigatório é incrivelmente fraca. Ele dá dois exemplos para justificar sua opinião.No primeiro exemplo, ele diz que chamar
Dispose
os controles do Windows Forms é entediante e desnecessário em cenários convencionais. No entanto, ele não menciona que,Dispose
na verdade, é chamado automaticamente por contêineres de controle nesses cenários principais.No segundo exemplo, ele afirma que um desenvolvedor pode assumir incorretamente que a instância de
IAsyncResult.WaitHandle
deve ser descartada de forma agressiva sem perceber que a propriedade inicializa preguiçosamente o identificador de espera, resultando em uma penalidade de desempenho desnecessária. Mas, o problema com este exemplo é que oIAsyncResult
próprio não adere às próprias diretrizes publicadas da Microsoft para lidar comIDisposable
objetos. Ou seja, se uma classe contém uma referência a umIDisposable
tipo, a própria classe deve implementarIDisposable
. SeIAsyncResult
essa regraDispose
fosse seguida, seu próprio método poderia tomar a decisão sobre qual de seus membros constituintes precisa ser eliminado.Portanto, a menos que alguém tenha um argumento mais convincente, continuarei no campo "sempre ligue para o descarte", com o entendimento de que haverá alguns casos marginais que surgem principalmente de más escolhas de design.
fonte
É realmente muito simples. Sei que foi respondido, mas tentarei novamente, mas tentarei mantê-lo o mais simples possível.
Geralmente, um destruidor nunca deve ser usado. É executado apenas .net quer que ele seja executado. Ele só será executado após um ciclo de coleta de lixo. Ele pode nunca ser executado durante o ciclo de vida de seu aplicativo. Por esse motivo, você nunca deve colocar nenhum código em um destruidor que 'deve' ser executado. Você também não pode confiar na existência de quaisquer objetos existentes na classe quando ela for executada (eles podem já ter sido limpos, pois a ordem em que os destruidores são executados não é garantida).
IDisposible deve ser usado sempre que você tiver um objeto que cria recursos que precisam de limpeza (ou seja, identificadores de arquivo e gráficos). Na verdade, muitos argumentam que qualquer coisa que você colocar em um destruidor deve ser colocada como descartável devido aos motivos listados acima.
A maioria das classes chamará dispose quando o finalizador for executado, mas isso é simplesmente uma proteção e nunca deve ser invocado. Você deve descartar explicitamente qualquer coisa que implemente IDisposable quando terminar de usá-lo. Se você implementar IDisposable, deverá chamar dispose no finalizer. Consulte http://msdn.microsoft.com/en-us/library/system.idisposable.aspx para obter um exemplo.
fonte
Aqui está outro bom artigo que limpa um pouco da névoa em torno de IDisposable, o GC e o descarte.
Chris Lyons WebLog Demystifying Dispose
fonte