CA1810: Inicializar campos estáticos de tipo de referencia insertados
Propiedad | Value |
---|---|
Identificador de la regla | CA1810 |
Título | Inicializar campos estáticos de tipo de referencia insertados |
Categoría | Rendimiento |
La corrección es problemática o no problemática | Poco problemático |
Habilitado de forma predeterminada en .NET 9 | No |
Causa
Un tipo de referencia declara un constructor estático explícito.
Descripción de la regla
Cuando un tipo declara un constructor estático explícito, el compilador Just-In-Time (JIT) agrega una comprobación a cada constructor de instancia y a cada método estático del tipo para asegurarse de que se ha llamado anteriormente al constructor estático. La inicialización estática se desencadena cuando se accede a cualquier miembro estático o cuando se crea una instancia del tipo. Sin embargo, la inicialización estática no se desencadena si declara una variable del tipo, pero no la usa, lo que puede ser importante si la inicialización cambia el estado global.
Cuando todos los datos estáticos se inicializan en línea y no se declara un constructor estático explícito, los compiladores de lenguaje intermedio común (CIL) agregan la beforefieldinit
marca y un constructor estático implícito, que inicializa los datos estáticos, a la definición de tipo CIL. En la mayoría de los casos, cuando el compilador JIT encuentra la marca beforefieldinit
, no se agregan las comprobaciones del constructor estático. Se garantiza que la inicialización estática se produzca en algún momento antes de acceder a los campos estáticos, pero no antes de que se invoque un método estático o un constructor de instancia. Tenga en cuenta que la inicialización estática puede producirse en cualquier momento después de declarar una variable del tipo.
Las comprobaciones del constructor estático pueden reducir el rendimiento. A menudo, un constructor estático se usa únicamente para inicializar campos estáticos, en cuyo caso solo debe asegurarse de que la inicialización estática se produzca antes del primer acceso de un campo estático. El comportamiento beforefieldinit
es adecuado para estos y la mayoría de los demás tipos. Solo es inapropiado cuando la inicialización estática afecta al estado global y se cumple una de las siguientes condiciones:
El efecto en el estado global es costoso y no es necesario si no se utiliza el tipo.
Se puede acceder a los efectos del estado global sin acceder a los campos estáticos del tipo.
Cómo corregir infracciones
Para corregir una infracción de esta regla, inicialice todos los datos estáticos cuando se declara y quite el constructor estático.
Cuándo suprimir las advertencias
Es seguro suprimir una advertencia de esta regla si se aplica uno de los siguientes casos:
- El rendimiento no es un problema.
- Los cambios en el estado global que causa la inicialización estática son caros o deben producirse sin excepciones antes de llamar a un método estático del tipo o de crear una instancia del tipo.
Supresión de una advertencia
Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.
#pragma warning disable CA1810
// The code that's violating the rule is on this line.
#pragma warning restore CA1810
Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none
del archivo de configuración.
[*.{cs,vb}]
dotnet_diagnostic.CA1810.severity = none
Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.
Ejemplo
En el ejemplo siguiente se muestra un tipo, StaticConstructor
, que infringe la regla y un tipo, NoStaticConstructor
, que reemplaza el constructor estático por inicialización alineada para cumplir la regla.
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
Tenga en cuenta la adición de la beforefieldinit
marca en la definición de la CIL para la NoStaticConstructor
clase .
.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