Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Uma instância de uma classe, um objeto, é criada usando a New
palavra-chave. As tarefas de inicialização geralmente devem ser executadas em novos objetos antes de serem usadas. As tarefas comuns de inicialização incluem abrir arquivos, conectar-se a bancos de dados e ler valores de chaves do Registro. O Visual Basic controla a inicialização de novos objetos usando procedimentos chamados construtores (métodos especiais que permitem o controle sobre a inicialização).
Depois que um objeto deixa o escopo, ele é liberado pelo CLR (Common Language Runtime). O Visual Basic controla a liberação de recursos do sistema usando procedimentos chamados destruidores. Juntos, os construtores e os destruidores oferecem suporte à criação de bibliotecas de classe robusta e previsível.
Usando construtores e destruidores
Construtores e destruidores controlam a criação e a destruição de objetos. Os procedimentos Sub New
e Sub Finalize
no Visual Basic inicializam e destroem objetos; eles substituem os métodos Class_Initialize
e Class_Terminate
usados no Visual Basic 6.0 e versões anteriores.
Sub-Novo
O Sub New
construtor só pode ser executado uma vez quando uma classe é criada. Ele não pode ser chamado explicitamente em qualquer lugar diferente da primeira linha de código de outro construtor da mesma classe ou de uma classe derivada. Além disso, o código no Sub New
método sempre é executado antes de qualquer outro código em uma classe. O Visual Basic criará implicitamente um Sub New
construtor em tempo de execução se você não definir explicitamente um Sub New
procedimento para uma classe.
Para criar um construtor para uma classe, crie um procedimento nomeado Sub New
em qualquer lugar na definição de classe. Para criar um construtor parametrizado, especifique os nomes e tipos de dados de argumentos da Sub New
mesma forma que você especificaria argumentos para qualquer outro procedimento, como no código a seguir:
Sub New(ByVal s As String)
Os construtores são frequentemente sobrecarregados, como no seguinte código:
Sub New(ByVal s As String, i As Integer)
Quando você define uma classe derivada de outra classe, a primeira linha de um construtor deve ser uma chamada para o construtor da classe base, a menos que a classe base tenha um construtor acessível que não tenha parâmetros. Uma chamada para a classe base que contém o construtor acima, por exemplo, seria MyBase.New(s)
. Caso contrário, MyBase.New
é opcional e o runtime do Visual Basic o chama implicitamente.
Depois de escrever o código para chamar o construtor do objeto pai, você pode adicionar qualquer código de inicialização adicional ao Sub New
procedimento.
Sub New
pode aceitar argumentos quando chamado como um construtor parametrizado. Esses parâmetros são passados do procedimento que chama o construtor, por exemplo, Dim AnObject As New ThisClass(X)
.
Sub-finalizar
Antes de liberar objetos, o CLR chama automaticamente o Finalize
método para objetos que definem um Sub Finalize
procedimento. O Finalize
método pode conter código que precisa ser executado pouco antes de um objeto ser destruído, como código para fechar arquivos e salvar informações de estado. Há uma pequena penalidade de desempenho para execução Sub Finalize
, portanto, você deve definir um Sub Finalize
método somente quando precisar liberar objetos explicitamente.
Observação
O coletor de lixo no CLR não descarta (e não pode) objetos não gerenciados, objetos que o sistema operacional executa diretamente, fora do ambiente CLR. Isso ocorre porque diferentes objetos não gerenciados devem ser descartados de maneiras diferentes. Essas informações não estão diretamente associadas ao objeto não gerenciado; ele deve ser encontrado na documentação do objeto. Uma classe que usa objetos não gerenciados deve descartá-los em seu Finalize
método.
O Finalize
destrutor é um método protegido que só pode ser chamado pela classe a que pertence ou por classes derivadas. O sistema chama Finalize
automaticamente quando um objeto é destruído, portanto, você não deve chamar Finalize
explicitamente de fora da implementação de Finalize
uma classe derivada.
Ao contrário de Class_Terminate
, que é executado assim que um objeto é definido como nulo, geralmente há um atraso entre o momento em que um objeto perde o escopo e quando o Visual Basic chama o destrutor Finalize
. O Visual Basic .NET permite um segundo tipo de destruidor, IDisposable.Disposeque pode ser chamado explicitamente a qualquer momento para liberar recursos imediatamente.
Observação
Um Finalize
destruidor não deve gerar exceções, pois elas não podem ser tratadas pelo aplicativo e podem fazer com que o aplicativo seja encerrado.
Como os métodos New e Finalize funcionam em uma hierarquia de classe
Sempre que uma instância de uma classe é criada, o CLR (Common Language Runtime) tenta executar um procedimento chamado New
, se ele existir nesse objeto.
New
é um tipo de procedimento chamado um constructor
que é usado para inicializar novos objetos antes que qualquer outro código em um objeto seja executado. Um New
construtor pode ser usado para abrir arquivos, conectar-se a bancos de dados, inicializar variáveis e cuidar de outras tarefas que precisam ser feitas antes que um objeto possa ser usado.
Quando uma instância de uma classe derivada é criada, o Sub New
construtor da classe base é executado primeiro, seguido por construtores em classes derivadas. Isso acontece porque a primeira linha de código em um Sub New
construtor usa a sintaxe MyBase.New()
para chamar o construtor da classe imediatamente acima de si na hierarquia de classe. O construtor Sub New
é então chamado para cada classe na hierarquia de classes até que o construtor da classe base seja invocado. Nesse ponto, o código no construtor da classe base é executado, seguido pelo código em cada construtor em todas as classes derivadas e o código nas classes mais derivadas é executado por último.
Quando um objeto não é mais necessário, o CLR chama o Finalize método para esse objeto antes de liberar sua memória. O Finalize método é chamado de destructor
porque executa tarefas de limpeza, como salvar informações de estado, fechar arquivos e conexões com bancos de dados e outras tarefas que devem ser feitas antes de liberar o objeto.
Interface IDisposable
Instâncias de classes frequentemente controlam recursos que não são gerenciados pelo CLR, como identificadores do Windows e conexões de banco de dados. Esses recursos devem ser descartados no Finalize
método da classe, para que sejam liberados quando o objeto for destruído pelo coletor de lixo. No entanto, o coletor de lixo destrói objetos somente quando o CLR requer mais memória livre. Isso significa que os recursos podem não ser liberados até muito tempo depois que o objeto sair do escopo.
Para complementar a coleta de lixo, suas classes podem fornecer um mecanismo para gerenciar ativamente os recursos do sistema se implementarem a IDisposable interface.
IDisposable tem um método, Disposeque os clientes devem chamar quando terminarem de usar um objeto. Você pode usar o Dispose método para liberar recursos imediatamente e executar tarefas como fechar arquivos e conexões de banco de dados. Ao contrário do Finalize
destruidor, o Dispose método não é chamado automaticamente. Os clientes de uma classe devem chamar Dispose explicitamente quando você deseja liberar recursos imediatamente.
Implementando IDisposable
Uma classe que implementa a IDisposable interface deve incluir estas seções de código:
Um campo para acompanhar se o objeto foi descartado:
Protected disposed As Boolean = False
Uma sobrecarga de Dispose que libera recursos da classe. Esse método deve ser chamado pelos métodos Dispose e
Finalize
da classe base.Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If Me.disposed = True End Sub
Uma implementação de Dispose que contém apenas o seguinte código:
Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub
Uma substituição do método
Finalize
que contém apenas o código a seguir:Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub
Derivação de uma classe que implementa IDisposable
Uma classe derivada de uma classe base que implementa a IDisposable interface não precisa substituir nenhum dos métodos base, a menos que use recursos adicionais que precisam ser descartados. Nessa situação, a classe derivada deve sobrescrever o método da Dispose(disposing)
classe base para descartar os recursos da classe derivada. Essa substituição deve chamar o método Dispose(disposing)
da classe base.
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposed Then
If disposing Then
' Insert code to free managed resources.
End If
' Insert code to free unmanaged resources.
End If
MyBase.Dispose(disposing)
End Sub
Uma classe derivada não deve sobrescrever os métodos Dispose e Finalize
da classe base. Quando esses métodos são chamados de uma instância da classe derivada, a implementação da classe base desses métodos chamam a substituição da classe derivada do método Dispose(disposing)
.
A coleta de lixo e o destruidor de finalização
O .NET Framework usa o sistema de coleta de lixo baseada em rastreamento de referência para liberar periodicamente recursos não utilizados. O Visual Basic 6.0 e versões anteriores usaram um sistema diferente chamado contagem de referência para gerenciar recursos. Embora ambos os sistemas executem a mesma função automaticamente, há algumas diferenças importantes.
O CLR destrói periodicamente objetos quando o sistema determina que esses objetos não são mais necessários. Os objetos são liberados mais rapidamente quando os recursos de sistema estão em fornecimento pequeno e, em caso contrário, menos frequente. O atraso entre quando um objeto perde o escopo e quando o CLR é lançado significa que, ao contrário dos objetos no Visual Basic 6.0 e versões anteriores, você não pode determinar exatamente quando o objeto será destruído. Em tal situação, dizem que os objetos têm tempo de vida não determinístico. Na maioria dos casos, o tempo de vida não determinístico não altera o modo como você grava aplicativos, desde que você se lembre de que o destruidor Finalize
pode não ser executado imediatamente quando um objeto perde o escopo.
Outra diferença entre os sistemas de coleta de lixo envolve o uso de Nothing
. Para aproveitar a contagem de referências no Visual Basic 6.0 e versões anteriores, programadores às vezes atribuíam Nothing
a variáveis de objeto para liberar as referências mantidas por essas variáveis. Se a variável tiver mantido a última referência ao objeto, os recursos do objeto serão liberados imediatamente. Em versões posteriores do Visual Basic, embora possa haver casos em que esse procedimento ainda é valioso, executá-lo nunca faz com que o objeto referenciado libere seus recursos imediatamente. Para liberar recursos imediatamente, use o método do Dispose objeto, se disponível. A única vez que você deve definir uma variável para Nothing
é quando o tempo de vida da variável se estende muito além do tempo que o coletor de lixo leva para detectar objetos órfãos.