Поделиться через


CA1810: инициализируйте статические поля ссылочного типа встроенными средствами

TypeName

InitializeReferenceTypeStaticFieldsInline

CheckId

CA1810

Категория

Microsoft.Performance

Критическое изменение

Не критическое

Причина

Ссылочный тип объявляет явный статический конструктор.

Описание правила

Если в типе объявляется явный статический конструктор, компилятор JIT добавляет проверку в каждый статический метод и конструктор экземпляров этого типа, чтобы убедиться, что статический конструктор уже вызывался ранее.Статическая инициализация выполняется при доступе к статическому члену или создании экземпляра типа.Однако, если объявляется переменная типа, которая не используется, статическая инициализация не выполняется. Это может быть важным, если инициализация изменяет глобальное состояние.

Если инициализация всех статических данных реализуется встроенными средствами и явный статический конструктор не объявляется, то компиляторы MSIL добавляют к определению типа MSIL флаг beforefieldinit и неявный статический конструктор, который инициализирует статические данные.Если компилятор JIT обнаруживает флаг beforefieldinit, то обычно проверки статических конструкторов не добавляются.Статическая инициализация будет обязательно выполнена перед доступом к любому статическому полю, но после вызова статического метода или конструктора экземпляров.Обратите внимание, что статическая инициализация может выполняться в любое время после объявления переменной типа.

Проверки статических конструкторов могут привести к снижению производительности.Статический конструктор, как правило, используется только для инициализации статических полей. В таком случае требуется лишь проверить, что статическая инициализация происходит перед первым доступом к статическому полю.Для этой и многих других целей прекрасно подходит флаг beforefieldinit.Его нельзя использовать только в том случае, если статическая инициализация влияет на глобальное состояние и выполняется одно из перечисленных ниже условий.

  • Изменение глобального состояния сопряжено с большими затратами, оно не требуется, если тип не используется.

  • Изменение глобального состояния можно осуществить без доступа к какому-либо статическому полю типа.

Устранение нарушений

Чтобы устранить нарушение данного правила, выполните инициализацию всех статических данных при их объявлении и удалите статический конструктор.

Отключение предупреждений

Отключение предупреждений о нарушении этого правила является безопасным в том случае, если не требуется высокая производительность, либо изменения глобального состояния за счет статической инициализации приводят к большим затратам, или необходимо обеспечить выполнение статической инициализации до вызова статического метода типа или создания экземпляра типа.

Пример

В следующем примере показан тип StaticConstructor, нарушающий данное правило, и тип NoStaticConstructor, который для устранения нарушения заменяет статический конструктор на встроенную инициализацию.

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");
      }
   }
}

Обратите внимание на добавление флага beforefieldinit в определении MSIL для класса NoStaticConstructor.

  

Связанные правила

CA2207: инициализируйте статические поля типа значений встроенными средствами