Construtores e Destrutores em C#

Construtores são métodos executados na criação da classe. As regras para definição de um construtor são:

  • o construtor deve ter o mesmo nome da classe;
  • não tem tipo de retorno;
  • é executado apenas um, apenas uma vez, no momento da criação do objeto;
  • não pode ser chamado diretamente;
  • deve ser “public”;

Um construtor “private” não permite que a classe seja criada ou instanciada. Isso pode ser conveniente em alguns aspectos, por exemplo, se a classe contiver somente membros “static”.

Tirando essas regras, os construtores são como os métodos convencionais e podem ser sobrecarregados e conter parâmetros. A função dos construtores é inicializar ou dar forma à classe. É nele que indicamos os valores dos campos de uma classe. Esses valores podem ser internos (no código) ou externos (passados por parâmetros). Veremos a implementação de construtores na classe “MinhaClasse” com que vínhamos trabalhando até então. Crie um novo arquivo chamado “exemploContrutor.cs” e digite o código abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      //cria o contrutor da classe
      public MinhaClasse()
      {
            Console.WriteLine("Estamos no construtor");
      }
 
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
      }
}

Compile e veja o resultado:

Note que foi preciso apenas criar a classe para que o construtor fosse executado. Modifique agora o código para o seguinte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      //campos da classe
      int v1, v2;
      //cria o contrutor da classe
      public MinhaClasse()
      {
            v1 = 1;
            v2 = 2;
      }
 
      public MinhaClasse(int p1, int p2)
      {
            v1 = p1;
            v2 = p2;
      }
 
      public void ImprimeValores()
      {
            Console.WriteLine("O valor de v1 e: {0} e v2 = {1}", v1, v2);
      }
 
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // Esta instância executa o primeiro construtor
            MinhaClasse obj1 = new MinhaClasse();
            // Esta instância executa o segundo construtor
            MinhaClasse obj2 = new MinhaClasse(10, 20);
            obj1.ImprimeValores();
            obj2.ImprimeValores();
      }
}

Compile e veja a saída do Console:

Como os valores de v1 e v2 são acessíveis somente à classe, colocá-los para serem inicializados no construtor é uma alternativa eficiente para garantir a integridade dos valores e do objeto criado, além oferecer mais opções para a criação e utilização de uma classe.

Os destrutores são métodos que são executados automaticamente quando o objeto não é mais utilizado e referenciado. A definição de um destrutor segue as seguintes regras:

  • Assim como o construtor, não pode ser chamado diretamente;
  • não tem tipo de retorno;
  • tem o mesmo nome da classe precedido de “~”;
  • não pode conter parâmetros;
  • não pode ser sobrecarregado;
  • não é herdado (processo de herança de classes);

Alguns problemas cercam o destrutores nas linguagens do .NET. Os destrutores foram concebidos principalmente para liberação de memória, processo que deveria ser feito manualmente pelo programador em linguagens como C e C++. Como no .NET a memória é gerenciada pelo “Garbage Collector”, não temos controle de quanto o destrutor será executado. Um exemplo de destrutor é dado no código abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      //cria o construtor da classe
      public MinhaClasse()
      {
            Console.WriteLine("Estamos no construtor");
      }
 
      //cria o destrutor da classe
      ~MinhaClasse()
      {
            Console.WriteLine("Estamos no destrutor");
      }
 
 
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
      }
}

Compile e veja a saída no console:

Apesar de quase instantâneo, neste caso, não podemos prever a execução do destrutor. Na prática, é melhor deixar o trabalho com o Garbage Collector.

Construtores e Destrutores

Um construtor é um método ou ação que define o objeto na sua construção ou criação. Por que precisamos de um construtor? Porque no momento da criação de um objeto, precisamos definir quais as características que ele deverá ter.

É bom deixar claro aqui que uma classe não pode ser entendida como um objeto. Como dito anteriormente, uma classe define um objeto. Podemos entender, então, que “o objeto existe, mas a classe não”. Um objeto gato pode possuir pelos brancos, mas a classe gato não. A classe gato pode sim definir qual será a cor dos pelos do objeto gato criado, mas não ser acessada diretamente. (para alguns programadores mais experientes, pode ter surgido uma dúvida em relação aos membros estáticos, assunto que será tratado e esclarecido mais adiante)

Até podemos criar um objeto sem suas características definidas, mas você conseguiria definir este objeto? Imaginando uma classe gato que criará um objeto gato sem características definidas, tente imaginar o objeto gato sem cor, sem pelos, sem saber o que é andar, enfim. O construtor então é um método especial que é automaticamente executado quando um objeto de uma classe é criado. É no construtor então que devemos definir as características principais do objeto no momento de sua criação, podendo elas serem padrão ou serem informadas externamente.

Um destrutor faz exatamente o contrário, ou seja, define como o objeto deve ser descartado. Muitas vezes o destrutor é ignorado pelo fato da destruição ou do descarte de um objeto ser implícito, mas em alguns casos devem se tomar alguns cuidados como limpeza de rastros ou vínculos deixados ou implementados por este objeto, e são nestes que os destrutores são necessários.