Initialisez les champs statiques de type référence en ligne
Mise à jour : novembre 2007
TypeName |
InitializeReferenceTypeStaticFieldsInline |
CheckId |
CA1810 |
Catégorie |
Microsoft.Performance |
Modification avec rupture |
Modification sans rupture |
Cause
Un type référence déclare un constructeur statique explicite.
Description de la règle
Lorsqu'un type déclare un constructeur statique explicite, le compilateur juste-à-temps (JIT, Just-In-Time) ajoute une vérification à chacun des méthodes statiques et constructeurs d'instances du type afin de garantir que le constructeur statique a été appelé précédemment. L'initialisation statique est déclenchée lorsque de l'accès à un membre statique ou lorsqu'une instance du type est créée. Toutefois, l'initialisation statique n'est pas déclenchée si vous déclarez une variable du type sans l'utiliser, ce qui peut s'avérer important si l'initialisation modifie l'état global.
Lorsque toutes les données statiques sont initialisées inline et lorsqu'un constructeur statique explicite n'est pas déclaré, les compilateurs de langage intermédiaire de Microsoft MSIL (MicroSoft Intermediate Language) ajoutent à la définition de type MSIL l'indicateur beforefieldinit et un constructeur statique implicite qui initialise les données statiques. Lorsque le compilateur JIT rencontre l'indicateur beforefieldinit, dans la plupart des cas, les vérifications du constructeur statique ne sont pas ajoutées. L'exécution de l'initialisation statique est garantie avant tout accès à un champ statique, mais non avant l'appel à une méthode statique ou à un constructeur d'instances. Remarquez que l'initialisation statique peut se produire n'importe quand après la déclaration d'une variable du type.
Les vérifications des constructeurs statiques peuvent diminuer les performances. Un constructeur statique est souvent utilisé uniquement pour initialiser des champs statiques, auquel cas il est seulement nécessaire de garantir que l'initialisation statique se produit avant le premier accès d'un champ statique. Le comportement de beforefieldinit est adapté à ceux-ci, ainsi qu'à la plupart des autres types. Il est inadapté uniquement lorsque l'initialisation statique affecte l'état global et lorsqu'une des conditions suivantes est vraie :
L'affectation sur un état global est coûteuse et n'est pas nécessaire si le type n'est pas utilisé.
Les effets de l'état global sont accessibles sans nécessiter d'accès à un champ statique du type.
Comment corriger les violations
Pour corriger une violation de cette règle, initialisez toutes les données statiques lorsqu'elles sont déclarées et supprimez le constructeur statique.
Quand supprimer les avertissements
Il est possible de supprimer sans risque un avertissement de cette règle si les performances ne constituent pas une priorité, ou si les modifications de l'état global dues à une initialisation statique sont coûteuses ou si leur exécution doit être garantie avant qu'une méthode statique du type soit appelée ou une instance du type créée.
Exemple
L'exemple suivant présente un type, StaticConstructor, qui enfreint la règle et un autre, NoStaticConstructor, qui remplace le constructeur statique au moyen d'une initialisation inline visant à satisfaire la règle.
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");
}
}
}
Remarquez l'ajout de l'indicateur beforefieldinit sur la définition MSIL pour la classe NoStaticConstructor.
.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