VB.NET – Um método Finalize deve ser adicionado ao implementar IDisposable?
-
02-07-2019 - |
Pergunta
No Visual Studio, quando digito a linha "Implements IDisposable
", o IDE adiciona automaticamente:
- a
disposedValue
variável de membro - a
Sub Dispose() Implements IDisposable.Dispose
- a
Sub Dispose(ByVal disposing As Boolean)
O Dispose()
deve ser deixado sozinho, e o código de limpeza deve ser colocado Dispose(disposing)
.
No entanto, o Descartar padrão de finalização diz que você também deve substituir Sub Finalize()
chamar Dispose(False)
.Por que o IDE também não adiciona isso?Devo adicioná-lo sozinho ou é de alguma forma chamado implicitamente?
EDITAR: Alguma ideia de por que o IDE adiciona automaticamente 80% do material necessário, mas deixa de fora o método Finalize?O objetivo desse tipo de recurso não é ajudar você não esquecer essas coisas?
EDITAR2: Obrigado a todos pelas excelentes respostas, agora faz todo o sentido!
Solução
Se você realmente estiver segurando recursos não gerenciados que não serão limpos automaticamente pelo coletor de lixo e limpando-os em seu dispede (), então sim, você deve fazer o mesmo em Finalize ().
Se você está implementando o IDisposable por algum outro motivo, a implementação do finalize () não é necessária.
A pergunta básica é a seguinte: se o dispede () não fosse chamado e seu lixo de objeto coletado, o memória vazaria? Se sim, implemente finalize. Se não, você não precisa. Além disso, evite a implementação da finalize "apenas porque é mais seguro". Objetos com finalizadores personalizados podem precisar de dois passes GC para libertá -los - uma vez para colocá -los na fila de finalizadores pendentes e um segundo passe para realmente libertar sua memória.
Outras dicas
Não, você não precisa ter o Finalize, a menos que tenha recursos não gerenciados para limpar.
Na maioria dos casos, o motivo pelo qual uma classe é descartável é porque ela mantém referências a outros objetos IDisposable gerenciados.Neste caso, nenhum método Finalize é necessário ou desejável.
Implements IDisposable
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
If disposing Then
' Free other state (managed objects).
End If
' Free your own state (unmanaged objects).
' Set large fields to null.
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Como outros disseram, você não precisa implementar um finalizador, a menos que esteja mantendo recursos não gerenciados diretamente. Além disso, supondo que você esteja trabalhando no .NET 2.0 ou posterior, é improvável que você precise implementar um finalizador, porque normalmente o SafeHandle pode ser usado para envolver seus recursos não gerenciados.
Eu escrevi a Postagem de blog bastante longa Cobrindo o plano de fundo e a implementação de idispos e finalizadores há algum tempo, o que pode valer a pena ler se você não estiver totalmente claro sobre isso.