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 9 | 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, StaticConstructor
dat in strijd is met de regel en een type, NoStaticConstructor
die 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