Quando um construtor estático é chamado em C #?

88

Quando eu tenho uma classe contendo um construtor estático, esse construtor é chamado quando o assembly que contém a classe é carregado pela primeira vez ou quando a primeira referência a essa classe é atingida?

Jason
fonte

Respostas:

93

Quando a aula é acessada pela primeira vez.

Construtores estáticos (guia de programação C #)

Um construtor estático é usado para inicializar qualquer dado estático ou para executar uma ação específica que precisa ser executada apenas uma vez. Ele é chamado automaticamente antes que a primeira instância seja criada ou qualquer membro estático seja referenciado.

Carra
fonte
6
Interessante que diz "antes que a primeira instância seja criada ou qualquer membro estático seja referenciado". Há alguma margem de manobra quando ele realmente é invocado.
Tim Barrass
6
@TimBarrass, devido a alguns outros requisitos de especificação, revela que "antes" é na verdade "imediatamente antes" - consulte o artigo de Jon Skeet referenciado em outra resposta - stackoverflow.com/a/1437372/477420
Alexei Levenkov
A static constructor is used to initialize any static dataNÃO. Melhor usar static initializerpara inicializar coisas estáticas.
Yousha Aleayoub
41

Não é tão simples quanto você pode esperar, apesar da documentação direta. O artigo de Jon Skeet http://csharpindepth.com/Articles/General/Beforefieldinit.aspx aborda essa questão em detalhes.

Resumo:

O construtor estático tem a garantia de ser executado imediatamente antes da primeira referência a um membro dessa classe - seja na criação de uma instância ou no próprio método / propriedade estática da classe.

Observe que os inicializadores estáticos (se não houver um construtor estático) garantem a execução a qualquer momento antes da primeira referência a um campo específico.

Greg Beech
fonte
O artigo mencionado está agora no site de Jon Skeet: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra
A seguir a pergunta stackoverflow.com/questions/32525628/… demonstrar o caso em que o comportamento "imediato" é bastante óbvio.
Alexei Levenkov,
1
Na verdade, acabei de passar por um caso em que um construtor estático foi chamado pouco antes de o método Main de um aplicativo de console começar a ser executado!
HerpDerpington
19

O construtor estático é chamado antes de você usar qualquer coisa na classe, mas exatamente quando isso acontece é com a implementação.

É garantido que será chamado antes que o primeiro membro estático seja acessado e antes que a primeira instância seja criada. Se a classe nunca for usada, o construtor estático não terá garantia de ser chamado.

Guffa
fonte
2
Quando isso acontece, não "depende da implementação" se essa implementação segue a especificação ECMA C #: "A execução de um construtor estático é disparada pelo primeiro dos seguintes eventos a ocorrer dentro de um domínio de aplicativo: [1] Uma instância do a classe é criada. [2] Qualquer um dos membros estáticos da classe é referenciado. " (Seção 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LucasH
1
@Luke: "O tempo exato de execução do construtor estático depende da implementação" ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@ Guffa: Essa pode ser a interpretação do autor do artigo, mas você não encontrará esse texto nas versões Microsoft ou ECMA / ISO da especificação C #.
LukeH
1

No caso do método estático ser chamado da classe pai, o construtor estático não será chamado, embora seja explicitamente especificado. Aqui está um exemplo que o construtor b não será chamado se b.methoda () for chamado.

static void Main(string[] args)
{
    b.methoda();
}

class a
{
    public static void methoda()
    {
        //using initialized method data
    }
}

class b : a
{
    static b()
    {
        //some initialization
    }
}    
Andrew
fonte
1

Parece haver uma pegadinha com construtores estáticos que é respondida em outro lugar, mas demorou um pouco para ser digerida em uma explicação simples. Todos os documentos e explicações afirmam que o construtor / inicializadores estáticos têm "garantia" de execução antes que a primeira classe seja instanciada ou o primeiro campo estático seja referenciado. A pegadinha surge quando você tenta colocar um singleton estático na classe que cria uma instância de si mesmo (galinha / ovo). Nesse caso, o construtor estático acaba sendo chamado após o construtor da instância - e no meu caso o construtor da instância continha código que dependia de alguns dados estáticos.

Construtor estático chamado após o construtor de instância?

O construtor estático pode ser executado após o construtor não estático. Este é um bug do compilador?

(a resposta para mim foi colocar o singleton em uma classe separada ou inicializar manualmente os dados estáticos no construtor de instância antes que seja necessário)

Etherman
fonte