A implementação de finalização e Dispose para Limpar Unmanaged Recursos
Observação: |
---|
Para obter informações sobre como finalização e eliminação usando o C++ , consulte Destruidores e Finalizers em Visual C++. |
Instâncias da classe geralmente encapsulam o controle sobre recursos que não são gerenciado pelo tempo de execução, sistema autônomo identificadores de janela (HWND), conexões de banco de dados e assim por diante. Portanto, você deve fornecer um explícito e uma maneira implícita disponível esses recursos. Fornecer controle implícito ao implementar o protegido Finalize em um objeto (sintaxe do destruidor em translation from VPE for Csharp e C++). O coletor de lixo chama esse método em algum momento depois que não forem quaisquer referências ao objeto válidas.
Em alguns casos, convém fornecer os programadores que usam um objeto com a capacidade de liberar explicitamente esses recursos externos antes do coletor de lixo libera o objeto. Se um recurso externo for escassos ou dispendiosa, melhor desempenho pode ser obtido se o programador explicitamente libera recursos quando não estão sendo usados. Para fornecer controle explícito, implementar o Dispose fornecido pela IDisposable. O consumidor do objeto deve telefonar esse método quando ele for concluído usando o objeto. Descartar pode ser chamado, mesmo que outras referências ao objeto ativas.
Observe que, mesmo quando você fornecer controle explícito usando Descartar, você deve fornecer implícita limpeza usando o Finalizar método. Finalizar oferece um backup para evitar que recursos permanentemente vazando se o programador não chamar Descartar.
Para obter mais informações sobre como implementar Finalizar and Descartar para limpar recursos não gerenciados, consulte Coleta de Lixo. O exemplo de código a seguir ilustra o padrão de design básica para a implementação de Descartar . Este exemplo requer o System espaço para nome.
' Design pattern for a base class.
Public Class Base
Implements IDisposable
' Field to handle multiple calls to Dispose gracefully.
Dim disposed as Boolean = false
' Implement IDisposable.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
If disposed = False Then
If disposing Then
' Free other state (managed objects).
disposed = True
End If
End If
' Free your own state (unmanaged objects).
' Set large fields to null.
End Sub
Protected Overrides Sub Finalize()
' Simply call Dispose(False).
Dispose (False)
End Sub
End Class
' Design pattern for a derived class.
Public Class Derived
Inherits Base
' Field to handle multiple calls to Dispose gracefully.
Dim disposed as Boolean = false
Protected Overloads Overrides Sub Dispose(disposing As Boolean)
If disposed = False Then
If disposing Then
' Release managed resources.
disposed = True
End If
End If
' Release unmanaged resources.
' Set large fields to null.
' Call Dispose on your base class.
Mybase.Dispose(disposing)
End Sub
' The derived class does not have a Finalize method
' or a Dispose method without parameters because it inherits
' them from the base class.
End Class
// Design pattern for a base class.
public class Base: IDisposable
{
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
}
// Use C# destructor syntax for finalization code.
~Base()
{
// Simply call Dispose(false).
Dispose (false);
}
}
// Design pattern for a derived class.
public class Derived: Base
{
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Release managed resources.
}
// Release unmanaged resources.
// Set large fields to null.
// Call Dispose on your base class.
base.Dispose(disposing);
}
// The derived class does not have a Finalize method
// or a Dispose method without parameters because it inherits
// them from the base class.
}
Para obter um exemplo de código mais detalhado que ilustra o padrão de design para implementar Finalizar and Descartar, see Implementando um método Dispose.
Personalizando um nome do método Dispose
Ocasionalmente, um nome de domínio específico é mais apropriado do que Descartar. Por exemplo, um encapsulamento de arquivo conveniente usar o nome de método Fechar. Nesse caso, implementar Descartar em particular e criar um público Fechar método de chamaDescartar. O exemplo de código a seguir ilustra esse padrão. Você pode substituir Fechar com um nome de método apropriado para seu domínio. Este exemplo requer o System espaço para nome.
' Do not make this method overridable.
' A derived class should not be allowed
' to override this method.
Public Sub Close()
' Call the Dispose method with no parameters.
Dispose()
End Sub
// Do not make this method virtual.
// A derived class should not be allowed
// to override this method.
public void Close()
{
// Call the Dispose method with no parameters.
Dispose();
}
Finalize
As regras a seguir descrevem as diretrizes de uso para o Finalizar método:
Implementar Finalizar somente em objetos que necessitam de finalização. Há custos de desempenho associados Finalizar métodos.
Se você precisar de um Finalizar método, considere a implementação de IDisposable para permitir que os usuários de sua classe de evitar o custo de invocar o Finalizar método.
Não torne o Finalizarmétodo mais visível. Ele deve ser protegido, not pública.
Finalizar método deve liberar os recursos externos que possui o objeto. Além disso, um Finalizar método deve versão apenas recursos que o objeto ocupou até. The Finalizar método não deve fazer referência a quaisquer outros objetos.
Fazer telefonar não diretamente um Finalizar método em um objeto Outros que a classe base do objeto. Isso não é uma operação válida no translation from VPE for Csharp linguagem de programação.
telefonar the Finalizar da classe base método a partir de um objeto Finalizar método.
Observação: A classe base Finalizar método é chamado automaticamente com a sintaxe do destruidor translation from VPE for Csharp e C++.
Dispose
As regras a seguir descrevem as diretrizes de uso para o Descartar método:
Implemente o padrão de design de descarte em um tipo que encapsula recursos explicitamente precisam ser liberado. Os usuários podem disponível recursos externos, chamando o público Descartar método.
Implemente o padrão de design de descarte em um tipo de base que normalmente tem derivada tipos que Isenção os recursos, mesmo se o tipo base não. Se o tipo de base tem um Fechar método, geralmente, isso indica a necessidade de implementar Descartar. Em tais casos, não implementam um Finalizar método no tipo de base. Finalizar deve ser implementado em quaisquer tipos derivados que introduza recursos que exigem limpeza.
disponível quaisquer recursos descartáveis um tipo possui em sua Descartar método.
Depois de Descartar foi chamado em uma instância, evitar o Finalizar método de execução chamando o GC.SuppressFinalize. A exceção a essa regra é a situação rara em que o trabalho deve ser concluído em Finalizar que não é coberto por Descartar.
telefonar Descartar método se ele implementa IDisposable.
Não assuma que Descartar será chamado. Também devem ser liberados pertencentes a um tipo de recursos não gerenciados em um Finalizar método no evento que Descartar não é chamado.
Lançar um ObjectDisposedException de métodos de instância deste tipo (diferente de Descartar) Quando os recursos são já descartados. Esta regra não se aplica à Descartar método porque ela deve ser que pode ser chamada várias vezes sem gerar uma exceção.
Propagar os planos de Descartar pela hierarquia de tipos base. The Descartar método deve liberar todos os recursos mantidos por este objeto e qualquer objeto que pertence a este objeto. Por exemplo, você pode criar um objeto sistema autônomo um TextReader que mantiver um Stream e um Encoding, que são criados pela TextReader sem conhecimento do usuário. Além disso, a Stream e o Encoding pode adquirir recursos externos. Quando você liga o Descartar método a TextReader, ela deve chamar por sua vez Descartar on the Stream e o Encoding, fazendo com que eles liberar seus recursos externos.
Considere não permitir que um objeto a ser usado após sua Descartar método foi chamado. Recriar um objeto que já tinha sido descartado é um padrão difíceis de implementar.
Permitir que um Descartar método a ser chamado mais de uma vez sem gerar uma exceção. O método deve fazer nada após a primeira telefonar.
Partes direitos autorais 2005 Microsoft Corporation. Todos os direitos reservados.
Partes direitos autorais Addison-Wesley Corporation. Todos os direitos reservados.
Para obter mais informações sobre diretrizes de design, consulte a "diretrizes de design do estrutura: Catálogo de convenções, idiomas e padrões para bibliotecas do .NET reutilizável"Krzysztof Cwalina e Brad Abrams, publicado pela Addison-Wesley, 2005.
Consulte também
Referência
Outros recursos
Diretrizes de Design para desenvolvimento bibliotecas de classe