Extension du programme de test et complet ci-dessous de observations, Fábio expose les détails JIT sensibles du comportement TypeAttributes.BeforeFieldInit
, en comparant .NET 3.5 à la dernière version (à partir de fin 2017) .NET 4.7.1 et démontre également les dangers potentiels pour les variations de type de construction dans chaque version elle-même. [1]
using System;
using System.Diagnostics;
class MyClass
{
public static Object _field = Program.init();
public static void TouchMe() { }
};
class Program
{
static String methodcall, fieldinit;
public static Object init() { return fieldinit = "fieldinit"; }
static void Main(String[] args)
{
if (args.Length != 0)
{
methodcall = "TouchMe";
MyClass.TouchMe();
}
Console.WriteLine("{0,18} {1,7} {2}", clrver(), methodcall, fieldinit);
}
};
est inférieure à la sortie de la console de l'exécution de ce programme dans toutes les combinaisons de {x86, x64} et {Debug, Release}. J'ai ajouté manuellement un symbole delta Δ
(non émis par le programme) pour mettre en évidence les différences entre les deux versions .NET.
2,0 .NET/3,5
2.0.50727.8825 x86 Debug
2.0.50727.8825 x86 Debug TouchMe fieldinit
2.0.50727.8825 x86 Release fieldinit
2.0.50727.8825 x86 Release TouchMe fieldinit
2.0.50727.8825 x64 Debug
2.0.50727.8825 x64 Debug TouchMe fieldinit
2.0.50727.8825 x64 Release
2.0.50727.8825 x64 Release TouchMe fieldinit
.NET 4.7.1
4.7.2556.0 x86 Debug
4.7.2556.0 x86 Debug TouchMe fieldinit
4.7.2556.0 x86 Release Δ
4.7.2556.0 x86 Release TouchMe Δ
4.7.2556.0 x64 Debug
4.7.2556.0 x64 Debug TouchMe fieldinit
4.7.2556.0 x64 Release
4.7.2556.0 x64 Release TouchMe Δ
Comme indiqué dans l'introduction, peut-être plus intéressant que la version 2,0/3,5 par rapport 4.7 deltas sont les différences dans le courant.Version NET, car ils montrent que, bien que le comportement d'initialisation de champ est aujourd'hui plus cohérent entre x86
et x64
qu'auparavant, il est encore encore possible de connaître une différence significative dans le comportement d'initialisation du champ d'exécution entre vos Debug
et Release
construit aujourd'hui . La sémantique dépend si vous appelez ou non une méthode statique disjointe ou apparemment sans relation sur la classe, donc si cela introduit un bug pour votre conception globale, il est susceptible d'être assez mystérieux et difficile à suivre vers le bas.
Remarques
1. Le programme ci-dessus utilise la fonction d'utilité suivante pour afficher la version actuelle CLR:
static String clrver()
{
var s = typeof(Uri).Assembly.Location;
return FileVersionInfo.GetVersionInfo(s).ProductVersion.PadRight(14) +
(IntPtr.Size == 4 ? " x86 " : " x64 ") +
#if DEBUG
"Debug ";
#else
"Release";
#endif
}
Est-ce que cela fonctionne le _static_ ctor? La classe n'a pas de constructeur public. En outre, est-ce sûr en ce qu'il ne fait pas courir un ctor deux fois, peut-être? – mafu
Oui, il exécute le ctor statique. Il est également sûr, le CLR permettra seulement le ctor statique être exécuté une fois. –
En effet, cette méthode est explicitement prévue pour les auteurs de compilateurs afin d'assurer une initialisation déterministe: http://blogs.msdn.com/cbrumme/archive/2003/04/15/51348.aspx – Ruben