Compartir a través de


CA1810: Inicializar campos estáticos de tipo de referencia insertados

Nombre de tipo

InitializeReferenceTypeStaticFieldsInline

Identificador de comprobación

CA1810

Categoría

Microsoft.Performance

Cambio problemático

Poco problemático

Motivo

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.Se desencadena la inicialización estática cuando se tiene acceso a cualquier miembro estático o cuando se crea una instancia del tipo.Sin embargo, no se desencadena la inicialización estática si declara una variable del tipo pero no se utiliza, lo que puede ser importante si la inicialización modifica el estado global.

Cuando se inicializan los datos estáticos en línea y no se declara un constructor estático explícito, los compiladores del lenguaje intermedio de Microsoft (MSIL) agregan un marcador beforefieldinit y un constructor estático implícito a la definición de tipo de MSIL.Cuando el compilador JIT encuentra la marca beforefieldinit, la mayoría de las veces no se agregan las comprobaciones de constructor estático.Es seguro que se producirá una inicialización estática en algún momento antes de que se obtenga acceso a cualquiera de los campos estáticos, pero no antes de la invocación de un método estático o un constructor de instancia.Observe 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.Con frecuencia un constructor estático se utiliza solo para inicializar campos estáticos, en cuyo caso debe asegurarse de que la inicialización estática se produce antes del primer acceso a un campo estático.El comportamiento beforefieldinit es adecuado para éstos y para la mayoría de los otros tipos.No es adecuado sólo cuando la inicialización estática afecta al estado global y una de las siguientes condiciones es verdadera:

  • El efecto sobre el estado global es costoso y no es necesario si no se utiliza el tipo.

  • Se puede tener acceso a los efectos sobre el estado global sin tener acceso a cualquier campo estático 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 advertencias

Es seguro suprimir una advertencia de esta regla si el rendimiento no es un aspecto importante; o si los cambios del estado global causados por la inicialización estática son costosos o si debe asegurarse de que se produzcan antes de llamar a un método estático del tipo o de crear una instancia del tipo.

Ejemplo

El siguiente ejemplo muestra un tipo StaticConstructor que infringe la regla, y un tipo NoStaticConstructor, que reemplaza el constructor estático por una inicialización en línea para cumplir la regla.

Imports System
Imports System.Resources

Namespace PerformanceLibrary

   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()

      Shared Private Function InitializeResourceString()

         Dim stringManager As New ResourceManager("strings", _
            System.Reflection.Assembly.GetExecutingAssembly())
         Return stringManager.GetString("string")

      End Function

   End Class

End Namespace
using System;
using System.Reflection;
using System.Resources;

namespace PerformanceLibrary
{
   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 class NoStaticConstructor
   {
      static int someInteger = 3;
      static string resourceString = InitializeResourceString();

      static string InitializeResourceString()
      {
         ResourceManager stringManager = 
            new ResourceManager("strings", Assembly.GetExecutingAssembly());
         return stringManager.GetString("string");
      }
   }
}

Tenga en cuenta la suma del marcador beforefieldinit en la definición de MSIL para la clase NoStaticConstructor.

  

Reglas relacionadas

CA2207: Inicializar campos estáticos de tipo de valor insertados