Partilhar via


CA1810: Inicializar campos estáticos do tipo de referência embutidos

Property valor
ID da regra CA1810
Título Inicializar campos estáticos do tipo de referência embutidos
Categoria Desempenho
A correção está quebrando ou não quebrando Sem quebra
Habilitado por padrão no .NET 8 Não

Motivo

Um tipo de referência declara um construtor estático explícito.

Descrição da regra

Quando um tipo declara um construtor estático explícito, o compilador just-in-time (JIT) adiciona uma verificação a cada método estático e construtor de instância do tipo para certificar-se de que o construtor estático foi chamado anteriormente. A inicialização estática é acionada quando qualquer membro estático é acessado ou quando uma instância do tipo é criada. No entanto, a inicialização estática não é acionada se você declarar uma variável do tipo, mas não usá-la, o que pode ser importante se a inicialização alterar o estado global.

Quando todos os dados estáticos são inicializados em linha e um construtor estático explícito não é declarado, os compiladores Common Intermediate Language (CIL) adicionam o sinalizador beforefieldinit e um construtor estático implícito, que inicializa os dados estáticos, à definição de tipo CIL. Quando o compilador JIT encontra o beforefieldinit sinalizador, na maioria das vezes as verificações do construtor estático não são adicionadas. É garantido que a inicialização estática ocorra em algum momento antes de qualquer campo estático ser acessado, mas não antes que um método estático ou construtor de instância seja invocado. Observe que a inicialização estática pode ocorrer a qualquer momento depois que uma variável do tipo é declarada.

As verificações estáticas do construtor podem diminuir o desempenho. Muitas vezes, um construtor estático é usado apenas para inicializar campos estáticos, caso em que você só deve certificar-se de que a inicialização estática ocorre antes do primeiro acesso de um campo estático. O beforefieldinit comportamento é apropriado para estes e para a maioria dos outros tipos. Só é inadequado quando a inicialização estática afeta o estado global e uma das seguintes opções é verdadeira:

  • O efeito sobre o estado global é caro e não é necessário se o tipo não for usado.

  • Os efeitos de estado global podem ser acessados sem acessar nenhum campo estático do tipo.

Como corrigir violações

Para corrigir uma violação dessa regra, inicialize todos os dados estáticos quando eles forem declarados e remova o construtor estático.

Quando suprimir avisos

É seguro suprimir um aviso desta regra se se aplicar uma das seguintes situações:

  • O desempenho não é uma preocupação.
  • As alterações de estado global causadas pela inicialização estática são caras ou devem ser garantidas antes que um método estático do tipo seja chamado ou uma instância do tipo seja criada.

Suprimir um aviso

Se você quiser apenas suprimir uma única violação, adicione diretivas de pré-processador ao seu arquivo de origem para desativar e, em seguida, reativar a regra.

#pragma warning disable CA1810
// The code that's violating the rule is on this line.
#pragma warning restore CA1810

Para desabilitar a regra de um arquivo, pasta ou projeto, defina sua gravidade como none no arquivo de configuração.

[*.{cs,vb}]
dotnet_diagnostic.CA1810.severity = none

Para obter mais informações, consulte Como suprimir avisos de análise de código.

Exemplo

O exemplo a seguir mostra um tipo, StaticConstructor, que viola a regra e um tipo, NoStaticConstructor, que substitui o construtor estático pela inicialização embutida para satisfazer a regra.

public class StaticConstructor
{
    static int someInteger;
    static string? resourceString;

    static StaticConstructor()
    {
        someInteger = 3;
        ResourceManager stringManager =
           new ResourceManager("strings", Assembly.GetExecutingAssembly());
        resourceString = stringManager.GetString("string");
    }

    public void Print()
    {
        Console.WriteLine(someInteger);
    }
}

public class NoStaticConstructor
{
    static int someInteger = 3;
    static string? resourceString = InitializeResourceString();

    static string? InitializeResourceString()
    {
        ResourceManager stringManager =
           new ResourceManager("strings", Assembly.GetExecutingAssembly());
        return stringManager.GetString("string");
    }

    public void Print()
    {
        Console.WriteLine(someInteger);
    }
}
Imports System
Imports System.Resources

Namespace ca1810

    Public Class StaticConstructor

        Shared someInteger As Integer
        Shared resourceString As String

        Shared Sub New()

            someInteger = 3
            Dim stringManager As New ResourceManager("strings",
            System.Reflection.Assembly.GetExecutingAssembly())
            resourceString = stringManager.GetString("string")

        End Sub

    End Class


    Public Class NoStaticConstructor

        Shared someInteger As Integer = 3
        Shared resourceString As String = InitializeResourceString()

        Private Shared Function InitializeResourceString()

            Dim stringManager As New ResourceManager("strings",
            System.Reflection.Assembly.GetExecutingAssembly())
            Return stringManager.GetString("string")

        End Function

    End Class

End Namespace

Observe a beforefieldinit adição do sinalizador na definição CIL para a NoStaticConstructor classe.

.class public auto ansi StaticConstructor
extends [mscorlib]System.Object
{
} // end of class StaticConstructor

.class public auto ansi beforefieldinit NoStaticConstructor
extends [mscorlib]System.Object
{
} // end of class NoStaticConstructor