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 9 | 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, StaticConstructor
který porušuje pravidlo a typ, NoStaticConstructor
který 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