CA1810: Zainicjuj wbudowane pola statyczne typu referencyjnego
Właściwości | Wartość |
---|---|
Identyfikator reguły | CA1810 |
Tytuł | Inicjuj pola statyczne typu referencyjnego śródwierszowo |
Kategoria | Wydajność |
Poprawka powodująca niezgodność lub niezgodność | Niezgodność |
Domyślnie włączone na platformie .NET 9 | Nie. |
Przyczyna
Typ odwołania deklaruje jawny konstruktor statyczny.
Opis reguły
Podczas gdy typ deklaruje jawny, statyczny konstruktor, kompilator just in time (JIT) do każdej metody statycznej dodaje sprawdzenie i konstruktora wystąpienia, aby upewnić się, że konstruktor statyczny został wcześniej wywołany. Inicjowanie statyczne jest wyzwalane, gdy dowolny statyczny element członkowski jest uzyskiwany lub gdy tworzone jest wystąpienie typu. Jednak inicjowanie statyczne nie jest wyzwalane, jeśli deklarujesz zmienną typu, ale nie używasz jej, co może być ważne, jeśli inicjowanie zmieni stan globalny.
Gdy wszystkie dane statyczne są inicjowane w tekście i jawny konstruktor statyczny nie jest zadeklarowany, kompilatory wspólnego języka pośredniego (CIL) dodają flagę beforefieldinit
i niejawny konstruktor statyczny, który inicjuje dane statyczne do definicji typu CIL. Gdy kompilator JIT napotka flagę beforefieldinit
, większość czasu sprawdzania konstruktora statycznego nie jest dodawana. Inicjowanie statyczne jest gwarantowane w pewnym momencie przed uzyskaniem dostępu do wszystkich pól statycznych, ale nie przed wywołaniem metody statycznej lub konstruktora wystąpienia. Należy pamiętać, że inicjowanie statyczne może wystąpić w dowolnym momencie po zadeklarowaniu zmiennej typu.
Sprawdzenia konstruktora statycznego mogą obniżyć wydajność. Często statyczny konstruktor jest używany tylko do inicjowania pól statycznych. W takim przypadku należy tylko upewnić się, że inicjowanie statyczne ma miejsce przed pierwszym dostępem do pola statycznego. Zachowanie beforefieldinit
jest odpowiednie dla tych i większości innych typów. Jest to nieodpowiednie tylko wtedy, gdy inicjowanie statyczne wpływa na stan globalny, a jedna z następujących wartości jest prawdziwa:
Wpływ na stan globalny jest kosztowny i nie jest wymagany, jeśli typ nie jest używany.
Dostęp do globalnych efektów stanu można uzyskać bez uzyskiwania dostępu do jakichkolwiek pól statycznych typu.
Jak naprawić naruszenia
Aby naprawić naruszenie tej zasady, zainicjuj wszystkie dane statyczne, gdy jest on zadeklarowany, i usuń konstruktor statyczny.
Kiedy pomijać ostrzeżenia
Można bezpiecznie pominąć ostrzeżenie z tej reguły, jeśli ma zastosowanie jedno z następujących elementów:
- Wydajność nie jest problemem.
- Globalne zmiany stanu spowodowane przez inicjowanie statyczne są kosztowne lub muszą być gwarantowane przed wywołaniem statycznej metody typu lub utworzeniem wystąpienia typu.
Pomijanie ostrzeżenia
Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.
#pragma warning disable CA1810
// The code that's violating the rule is on this line.
#pragma warning restore CA1810
Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none
w pliku konfiguracji.
[*.{cs,vb}]
dotnet_diagnostic.CA1810.severity = none
Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.
Przykład
W poniższym przykładzie pokazano typ , StaticConstructor
który narusza regułę i typ , NoStaticConstructor
który zastępuje konstruktor statyczny inline inicjalizacji, aby spełnić regułę.
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
Zwróć uwagę na beforefieldinit
dodanie flagi w definicji CIL dla NoStaticConstructor
klasy.
.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