VB .NET - Liberando os objetos de forma apropriada


Qual a melhor forma de liberar os recursos usados por um objeto que foi alocado usando recursos do sistema ?

O Visual Basic fornece 3 métodos primários para liberar os recursos de objetos que implementam a interface IDisposable:

  1. Chamar o método Dispose() do objeto exposto pela interface IDisposable e implementado pelo tipo do objeto. Este é o método mais direto de liberar recursos. O objeto não será usado desde que Dispose() foi chamado;
  2. Usar o bloco de instrução Using/End Using. Este bloco de instruções chama automaticamente o método Dispose do objeto quando o bloco termina ou a execução sai fora do bloco por qualquer razão;

Nota: Se você ainda não conhece a instrução Using/End Using ela esta disponível somente a partir da versão 2.0 da plataforma .NET e tem a seguinte sintaxe:

Using { resourcelist | resourceexpression }
    [ statements ]
End Using

Algumas vezes o seu código necessita usar um recurso não gerenciado como o tratamento de arquivos, uma conexão SQL, etc. Nestes casos usar o bloco de código Using/End Using garante que a liberação dos recursos serão efetivadas quando seu código acabar de usá-los. Recursos gerenciados são liberados pelo coletor de lixo (GC) da plataforma .NET de forma automática.

A instrução Using é usada para usar recursos e ter a certeza que estes recursos serão liberados no fim do bloco da instrução End Using. A seguir um exemplo de utilização no VB.NET :

UUsing conn As New SqlConnection(dsn)
      Using cmd As New SqlCommand("SELECT * FROM Clientes", conn)
          conn.Open()
            Using rdr As SqlDataReader = cmd.ExecuteReader()
              While rdr.Read()
                 Console.WriteLine(rdr(0))
               End While
           End Using
      End Using
End Using
using (SqlConnection conn = new SqlConnection(dsn))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Clientes", conn))
{
  conn.Open();
  using (SqlDataReader rdr = cmd.ExecuteReader())
  {
   while (rdr.Read())
      Console.WriteLine(rdr[0]);
  }
}
VB.NET C# (bem mais elegante,não acham ??)
  1. Deixar o objeto sem referência e fora do escopo, ou atribuir Nothing a objeto. Esta prática não é aconselhável pois o processo do coletor de lixo é quem irá controlar quando os recursos adicionais serão liberados e você não tem controle sobre isto quando escolhe esta opção.

De forma geral o construtor para uma classe pode alocar recursos externos ou compartilhados que precisam ser propriamente liberados o mais rápido possível quando não forem mais necessários. Algumas classes implementam seus próprios métodos para efetuar esta tarefa.

Muitos objetos que tratam recursos externos ou compartilhados implementam a interface System.IDisposable. Esta interface expõe o método Dispose() que o seu código pode chamar para liberar recursos. Você mesmo pode incluir a interface IDisposable em suas próprias classes:

Class MinhaClasse
        Implements IDisposable

Protected Overridable Sub Dispose( ) Implements IDisposable.Dispose
       ' ----- inclua o seu código para liberar recursos aqui.
End Sub
End Class

Para classes que não alocam recursos externos ou compartilhados, ou quando o tratamento de tais recursos por um período longo de tempo não irá degradar o sistema ou o desempenho da aplicação, o método Finalize() pode ser usado para liberar estes recursos.

Para tais classes não há necessidade de um processamento especial para destruir o objeto. Simplesmente espere até que o objeto seja liberado ou atribua um Nothing ao mesmo.

Nota: Se você desejar implementar a interface IDisposable() na sua classe, você deverá também sobrescrever o método Finalize() para ter certeza de que os recursos serão liberados mesmo se o usuário da classe esquecer de chamar o método Dispose(). Ex:

Protected Overrides Sub Finalize( )
' ----- inclua o seu código para liberar recursos aqui.
End Sub

De forma geral é recomendado que você efetue chame o método Dispose() dos objetos que estão sendo utilizados para garantir a liberação da memória que esta sendo usada.

Se você não chamar o Dispose() não saberá quanto tempo os recursos estarão sendo consumidos o que acarretará um uso maior da memória comprometendo a escalabilidade do sistema.

Obs: A utilização do Dispose() irá consumir recursos do sistema visto que estamos realizando uma tarefa a mais.

Até o próximo artigo VB.NET...

referências:


José Carlos Macoratti