Static Constructors – Mito ou realidade?

Se tem uma coisa que as pessoas que trabalham com C# pouco conhecem e utilizam, podem apostar, são Static Constructors.

E sinceramente, eu demorei bastante para saber de sua existência. Estava pesquisando sobre corretas implementações do Singleton Pattern e em uma delas, me flagrei necessitado a usar um Static Constructor.

Portanto, antes de falar sobre Singleton aqui, achei melhor dedicar um post exclusivo para os construtores estáticos.

Em sua essência, Static Constructors têm como principal objetivo inicializar os membros estáticos de uma classe antes que:

  • Qualquer instância desta classe seja criada; ou
  • Qualquer membro estático seja referenciado dentro do application domain.

Isso nos dá um recurso poderoso de inicialização centralizada dos membros estáticos ou uma opção caso queiramos executar alguma ação de setup da classe apenas uma vez por AppDomain (o que pode garantir thread-safe nas soluções em que for usado).

Mas para alguns isso pode soar estranho, afinal C#, assim como a maioria das linguagens OOP atuais, possui o recurso de type initialization. Deste modo, é comum encontrarmos trechos de código como:

class Program
{
       static int count = 1000
}

Porém, é possível ainda que a mesma variável count seja inicializada desta forma:

class Program
{
       static int count;
       static Program()
       {
              count = 1000;
       }
}

De acordo com a especificação do C# (ECMA 334), existem algumas regras básicas para usar Static Constructors:

  • Só pode existir um StaticConstructor por classe.
  • O Static Constructor não pode possuir parâmetros.
  • O Static Constructor somente pode acessar membros estáticos da classe.
  • O Static Constructor não pode ter modificador de acesso.

Superadas essas limitações, por que utilizar Static Constructors e não type-initializers?

Vamos supor que na classe Program exista um método que utilize a variável estática count.

Ao NÃO escrevermos um construtor estático, o compilador do C# marcará a classe com o atributo beforeFieldInit.

E o que isso quer dizer?

Conforme o ECMA do CLI, beforeFieldInit specifies that calling static methods of the type does not force the system to initialize the type.”.

Em outras palavras, não é garantido a inicialização da variável ao acessar o método dependente, e sim ao primeiro acesso de uma variável do mesmo tipo (int no caso).

Se a classe possuir construtor estático, o compilador não decorará a classe com beforeFieldInit, nos garantindo que as variáveis estejam inicializadas:

  • Antes do primeiro acesso a qualquer campo estático ou de instância; ou
  • Antes da primeira invocação para qualquer método estático, de instância ou virtual.

Isso soluciona alguns problemas de inicialização de recursos, incluindo os campos estáticos utilizados na sincronização de Singleton Patterns (que veremos no próximo post!)

Além de centralizar a inicialização de membros estáticos, os construtores estáticos nos garantem a inicialização dos tipos antes de qualquer utilização dependente posterior, evitando exceções com type-initializers.

Até a próxima, espero poder ter tempo pra postar em breve!

2 respostas em “Static Constructors – Mito ou realidade?

  1. Pingback: Singleton Pattern: The truth behind « Arquitetura e Desenvolvimento de Software

  2. Boa tarde Bernardo!

    Muito bom o post! Só tenho uma pergunta:
    Mesmo utilizando um type-initializers. E supondo que exista um método estático que dependa dessa variável. Porém essa variável não tenha sido iniciada, nem qualquer outra do seu tipo=> Ao chamar o método ele forçará para essa variável ser iniciada.

    Você afirmar que podem existir Exceptions de inicialização delas “suponho eu que seja 0,000000001% dos casos” mesmo supondo isso eu não afirmaria! Você já viu erros desse tipo?

    Creio que em Runtime isso acontece e seja improvável esse erro. Agora se você falar que já aconteceu com você tudo bem. Talvez na versão 2.0 quando o JIT não era tão bom assim? Vai saber né rs.

    De qualquer forma=> O Static Constructors é bom usar para centralização de inicialização de variáveis estáticas. Mas uma questão de organização mesmo.

    Obrigado!

Deixe um comentário