CA1810: Inizializzare i campi statici del tipo di riferimento inline
Proprietà | valore |
---|---|
ID regola | CA1810 |
Title | Inizializzare i campi statici del tipo di riferimento inline |
Categoria | Prestazioni |
La correzione causa un'interruzione o meno | Non causa un'interruzione |
Abilitato per impostazione predefinita in .NET 9 | No |
Causa
Un tipo riferimento dichiara un costruttore statico esplicito.
Descrizione regola
Quando un tipo dichiara un costruttore statico esplicito, tramite il compilatore JIT (Just-In-Time) viene aggiunto un controllo a ogni metodo statico del tipo e a ogni costruttore di istanza del tipo per assicurare che il costruttore statico sia stato precedentemente chiamato. L'inizializzazione statica viene attivata quando si accede a un membro statico o quando viene creata un'istanza del tipo. Tuttavia, l'inizializzazione statica non viene attivata se si dichiara una variabile del tipo ma non la si usa, che può essere importante se l'inizializzazione cambia lo stato globale.
Quando tutti i dati statici vengono inizializzati inline e non viene dichiarato un costruttore statico esplicito, i compilatori CIL (Common Intermediate Language) aggiungono il beforefieldinit
flag e un costruttore statico implicito, che inizializza i dati statici, alla definizione del tipo CIL. Quando il compilatore JIT rileva il beforefieldinit
flag, nella maggior parte dei casi i controlli del costruttore statico non vengono aggiunti. L'inizializzazione statica viene garantita in un determinato momento prima dell'accesso a qualsiasi campo statico, ma non prima che venga richiamato un metodo statico o un costruttore di istanza. Si noti che l'inizializzazione statica può verificarsi in qualsiasi momento dopo la dichiarazione di una variabile del tipo.
I controlli dei costruttori statici possono ridurre le prestazioni. Spesso un costruttore statico viene usato solo per inizializzare i campi statici, nel qual caso è necessario assicurarsi che l'inizializzazione statica venga eseguita solo prima del primo accesso di un campo statico. Il beforefieldinit
comportamento è appropriato per questi e la maggior parte degli altri tipi. È inappropriato solo quando l'inizializzazione statica influisce sullo stato globale e una delle condizioni seguenti è vera:
L'effetto sullo stato globale è costoso e non è necessario se il tipo non viene usato.
È possibile accedere agli effetti dello stato globale senza accedere ad alcun campo statico del tipo.
Come correggere le violazioni
Per correggere una violazione di questa regola, inizializzare tutti i dati statici quando vengono dichiarati e rimuovere il costruttore statico.
Quando eliminare gli avvisi
È possibile eliminare un avviso da questa regola se si applica uno dei seguenti elementi:
- Le prestazioni non sono un problema.
- Le modifiche di stato globali causate dall'inizializzazione statica sono costose o devono essere garantite prima che venga chiamato un metodo statico del tipo o venga creata un'istanza del tipo.
Eliminare un avviso
Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.
#pragma warning disable CA1810
// The code that's violating the rule is on this line.
#pragma warning restore CA1810
Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none
su nel file di configurazione.
[*.{cs,vb}]
dotnet_diagnostic.CA1810.severity = none
Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.
Esempio
Nell'esempio seguente viene illustrato un tipo, StaticConstructor
, che viola la regola e un tipo , NoStaticConstructor
, che sostituisce il costruttore statico con l'inizializzazione inline per soddisfare la regola.
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
Si noti l'aggiunta beforefieldinit
del flag nella definizione CIL per la NoStaticConstructor
classe .
.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