terça-feira, 19 de maio de 2009

C# - Garbage Collection e Destrutores

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2009/05/19/C-Garbage-Collection-e-Destrutores.aspx


O Common Language Runtime (CLR) faz o gerenciamento automático de memória usando o garbage collector para recuperar a memória usada por objetos que não estão mais sendo usados, então a memória pode ser usada por outros objetos.

Para chamar um destrutor, o C# usa um ~ (tio) antes do nome do construtor (sem parâmetros). Ao atribuir null a um objeto, o garbage collector não é executado no mesmo momento, o que significa que o objeto continua na memória e o método destrutor não é chamado na mesma hora. Não é possível determinar quando o garbage collector é chamado, portanto é sempre aconselhável evitar o uso de destrutores.

O código de exemplo abaixo utiliza destrutores, porém é necessário utilizar os métodos Collect() e WaitForPendingFinalizers() presentes na classe GC, da namespace System, para que o código funcione corretamente. O método Collect() chama o garbage collector, porém ele roda em um thread em paralelo com o resto do código. Isso força a utilização de WaitForPendingFinalizers() para esperar que o thread do garbage collector termine a sua execução para depois continuar o código no thread que chamou o método.

Segue o exemplo:

   1:  class Empregado

   2:  {

   3:      private string primeiroNome;

   4:      private string ultimoNome;

   5:      private static int contador = 0;

   6:          

   7:      public Empregado(string nome, string sobrenome)

   8:      {

   9:          contador++;

  10:          primeiroNome = nome;

  11:          ultimoNome = sobrenome;

  12:      }

  13:   

  14:      ~Empregado()

  15:      {

  16:          contador--;

  17:      }

  18:   

  19:      public string Nome

  20:      {

  21:          get

  22:          {

  23:              return primeiroNome;

  24:          }

  25:      }

  26:   

  27:      public string Sobrenome

  28:      {

  29:          get

  30:          {

  31:              return ultimoNome;

  32:          }

  33:      }

  34:   

  35:      public static int Contador

  36:      {

  37:          get

  38:          {

  39:              return contador;

  40:          }

  41:      }

  42:  }


A classe do programa:

   1:  class Program

   2:  {

   3:      static void Main(string[] args)

   4:      {

   5:          Empregado empregado1 = new Empregado("Thiago", "Milaneze");

   6:          Empregado empregado2 = new Empregado("Eric", "Milaneze");

   7:   

   8:          Console.WriteLine("Número de empregados: " + Empregado.Contador.ToString());

   9:          Console.WriteLine("Empregado 1: " + empregado1.Nome + " " + empregado1.Sobrenome);

  10:          Console.WriteLine("Empregado 2: " + empregado2.Nome + " " + empregado2.Sobrenome);

  11:   

  12:          empregado1 = null;

  13:          empregado2 = null;

  14:   

  15:          GC.Collect();

  16:          GC.WaitForPendingFinalizers();

  17:   

  18:          Console.WriteLine("\nNúmero de empregados: " + Empregado.Contador.ToString());

  19:   

  20:          Console.ReadLine();

  21:      }

  22:  }

Nenhum comentário: