Dela via


CA1810: Initiera statiska fält av referenstyp infogade

Property Värde
Regel-ID CA1810
Title Initiera statiska fält av referenstyp infogade
Kategori Prestanda
Korrigeringen är icke-bakåtkompatibel Icke-icke-bryta
Aktiverad som standard i .NET 8 Nej

Orsak

En referenstyp deklarerar en explicit statisk konstruktor.

Regelbeskrivning

När en typ deklarerar en explicit statisk konstruktor lägger JIT-kompilatorn (just-in-time) till en kontroll till varje statisk metod och instanskonstruktor av typen för att kontrollera att den statiska konstruktorn tidigare anropades. Statisk initiering utlöses när en statisk medlem används eller när en instans av typen skapas. Statisk initiering utlöses dock inte om du deklarerar en variabel av typen men inte använder den, vilket kan vara viktigt om initieringen ändrar globalt tillstånd.

När alla statiska data initieras infogade och en explicit statisk konstruktor inte deklareras lägger CIL-kompilatorer (Common Intermediate Language) till beforefieldinit flaggan och en implicit statisk konstruktor, som initierar statiska data, i definitionen av CIL-typen. När JIT-kompilatorn stöter beforefieldinit på flaggan läggs de statiska konstruktorkontrollerna för det mesta inte till. Statisk initiering sker garanterat någon gång innan statiska fält används, men inte innan en statisk metod eller instanskonstruktor anropas. Observera att statisk initiering kan ske när som helst när en variabel av typen har deklarerats.

Statiska konstruktorkontroller kan minska prestandan. Ofta används en statisk konstruktor endast för att initiera statiska fält, i vilket fall du bara måste se till att statisk initiering sker före den första åtkomsten av ett statiskt fält. Beteendet beforefieldinit är lämpligt för dessa och de flesta andra typer. Det är bara olämpligt när statisk initiering påverkar det globala tillståndet och något av följande är sant:

  • Effekten på det globala tillståndet är dyr och krävs inte om typen inte används.

  • De globala tillståndseffekterna kan nås utan åtkomst till statiska fält av typen.

Så här åtgärdar du överträdelser

Åtgärda ett brott mot den här regeln genom att initiera alla statiska data när de deklareras och ta bort den statiska konstruktorn.

När du ska ignorera varningar

Det är säkert att ignorera en varning från den här regeln om något av följande gäller:

  • Prestanda är inte ett problem.
  • Globala tillståndsändringar som orsakas av statisk initiering är dyra eller måste garanteras ske innan en statisk metod av typen anropas eller en instans av typen skapas.

Ignorera en varning

Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.

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

Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none i konfigurationsfilen.

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

Mer information finns i Så här utelämnar du kodanalysvarningar.

Exempel

I följande exempel visas en typ, StaticConstructor, som bryter mot regeln och en typ, NoStaticConstructor, som ersätter den statiska konstruktorn med infogad initiering för att uppfylla regeln.

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

Observera tillägget av beforefieldinit flaggan i CIL-definitionen för NoStaticConstructor klassen.

.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