Share via


CA1810: Referentietype statische velden inline initialiseren

Eigenschappen Weergegeven als
Regel-id CA1810
Titel Statische velden van referentietype inline initialiseren
Categorie Prestaties
Oplossing is brekend of niet-brekend Niet-brekend
Standaard ingeschakeld in .NET 8 Nee

Oorzaak

Een verwijzingstype declareert een expliciete statische constructor.

Beschrijving van regel

Wanneer een type een expliciete statische constructor declareert, voegt de JIT-compiler (Just-In-Time) een controle toe aan elke statische methode en instantieconstructor van het type om ervoor te zorgen dat de statische constructor eerder is aangeroepen. Statische initialisatie wordt geactiveerd wanneer een statisch lid wordt geopend of wanneer een exemplaar van het type wordt gemaakt. Statische initialisatie wordt echter niet geactiveerd als u een variabele van het type declareert, maar deze niet gebruikt, wat belangrijk kan zijn als de initialisatie de globale status wijzigt.

Wanneer alle statische gegevens inline worden geïnitialiseerd en er geen expliciete statische constructor wordt gedeclareerd, voegen CIL-compilers (Common Intermediate Language) de beforefieldinit vlag en een impliciete statische constructor toe, die de statische gegevens initialiseert, aan de definitie van het CIL-type. Wanneer de JIT-compiler de beforefieldinit vlag tegenkomt, worden de meeste tijd de statische constructorcontroles niet toegevoegd. Statische initialisatie wordt gegarandeerd op een bepaald moment uitgevoerd voordat statische velden worden geopend, maar niet voordat een statische methode of instantieconstructor wordt aangeroepen. Houd er rekening mee dat statische initialisatie op elk gewenst moment kan optreden nadat een variabele van het type is gedeclareerd.

Statische constructorcontroles kunnen de prestaties verminderen. Vaak wordt een statische constructor alleen gebruikt om statische velden te initialiseren. In dat geval moet u er alleen voor zorgen dat statische initialisatie plaatsvindt voordat een statisch veld wordt geopend. Het beforefieldinit gedrag is geschikt voor deze en de meeste andere typen. Het is alleen ongepast wanneer statische initialisatie van invloed is op de globale status en een van de volgende is waar:

  • Het effect op de globale status is duur en is niet vereist als het type niet wordt gebruikt.

  • De globale statuseffecten kunnen worden geopend zonder toegang te krijgen tot statische velden van het type.

Schendingen oplossen

Als u een schending van deze regel wilt oplossen, initialiseert u alle statische gegevens wanneer deze wordt gedeclareerd en verwijdert u de statische constructor.

Wanneer waarschuwingen onderdrukken

Het is veilig om een waarschuwing van deze regel te onderdrukken als een van de volgende van toepassing is:

  • Prestaties zijn geen probleem.
  • Globale statuswijzigingen die worden veroorzaakt door statische initialisatie zijn duur of moeten gegarandeerd plaatsvinden voordat een statische methode van het type wordt aangeroepen of een exemplaar van het type wordt gemaakt.

Een waarschuwing onderdrukken

Als u slechts één schending wilt onderdrukken, voegt u preprocessorrichtlijnen toe aan uw bronbestand om de regel uit te schakelen en vervolgens opnieuw in te schakelen.

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

Als u de regel voor een bestand, map of project wilt uitschakelen, stelt u de ernst none ervan in op het configuratiebestand.

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

Zie Codeanalysewaarschuwingen onderdrukken voor meer informatie.

Opmerking

In het volgende voorbeeld ziet u een type, StaticConstructordat in strijd is met de regel en een type, NoStaticConstructordie de statische constructor vervangt door inline initialisatie om te voldoen aan de regel.

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

Let op de toevoeging van de beforefieldinit vlag op de CIL-definitie voor de NoStaticConstructor klasse.

.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