Share via


CA1810: Inicializujte odkazový typ statického pole vloženě

Vlastnost Hodnota
ID pravidla CA1810
Název Inicializujte odkazový typ statického pole vloženě
Kategorie Výkon
Oprava způsobující chybu nebo chybu způsobující chybu Nenarušující
Povoleno ve výchozím nastavení v .NET 8 No

Příčina

Typ odkazu deklaruje explicitní statický konstruktor.

Popis pravidla

Pokud typ deklaruje explicitní statický konstruktor, kompilátor just-in-time (JIT) ke každé statické metodě a konstruktoru instance tohoto typu přidá kontrolu, zda již byl dříve statický konstruktor zavolán. Statická inicializace se aktivuje při přístupu ke statickému členu nebo při vytvoření instance typu. Statická inicializace se však neaktivuje, pokud deklarujete proměnnou typu, ale nepoužíváte ji, což může být důležité, pokud inicializace změní globální stav.

Pokud jsou všechna statická data inicializována vložena a explicitní statický konstruktor není deklarován, kompilátory CIL (Common Intermediate Language) přidávají beforefieldinit příznak a implicitní statický konstruktor, který inicializuje statická data, do definice typu CIL. Když kompilátor JIT narazí na beforefieldinit příznak, většinou se nepřidají kontroly statického konstruktoru. Statické inicializace je zaručeno, že se v určitém okamžiku objeví dříve, než budou vyvolána statická pole, ale ne před vyvolání statické metody nebo konstruktoru instance. Mějte na paměti, že statická inicializace může dojít kdykoli po deklaraci proměnné typu.

Kontroly statického konstruktoru mohou snížit výkon. Statický konstruktor se často používá pouze k inicializaci statických polí, v takovém případě je nutné zajistit, aby před prvním přístupem ke statickému poli došlo pouze ke statické inicializaci. Chování beforefieldinit je vhodné pro tyto a většinu ostatních typů. Je to nevhodné jenom v případech, kdy statická inicializace ovlivňuje globální stav a platí jedna z následujících skutečností:

  • Vliv na globální stav je nákladný a nevyžaduje se, pokud se typ nepoužívá.

  • Globální stavové efekty jsou přístupné bez přístupu ke statickým polím typu.

Jak opravit porušení

Chcete-li opravit porušení tohoto pravidla, inicializujte všechna statická data při deklaraci a statický konstruktor odeberte.

Kdy potlačit upozornění

Pokud platí některá z následujících možností, je bezpečné potlačit upozornění z tohoto pravidla:

  • Výkon není problém.
  • Globální změny stavu způsobené statickou inicializací jsou nákladné nebo musí být zaručeny před zavoláním statické metody typu nebo vytvořením instance typu.

Potlačení upozornění

Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.

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

Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none konfiguračním souboru.

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

Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.

Příklad

Následující příklad ukazuje typ, StaticConstructorkterý porušuje pravidlo a typ, NoStaticConstructorkterý nahrazuje statický konstruktor inicializací inicializace, která vyhovuje pravidlu.

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

Všimněte si přidání příznaku beforefieldinit v definici CIL pro NoStaticConstructor třídu.

.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