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 9 | 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