Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Remarque
Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Elle inclut les changements de spécification proposés, ainsi que les informations nécessaires à la conception et au développement de la fonctionnalité. Ces articles sont publiés jusqu'à ce que les changements proposés soient finalisés et incorporés dans la spécification ECMA actuelle.
Il peut y avoir des divergences entre la spécification de la fonctionnalité et l'implémentation réalisée. Ces différences sont capturées dans les notes de réunion de conception de langage (LDM) pertinentes .
Vous pouvez en savoir plus sur le processus d’adoption des speclets de fonctionnalités dans la norme de langage C# dans l’article sur les spécifications.
Problème de champion : https://github.com/dotnet/csharplang/issues/2608
Résumé
Bien que la plateforme .NET ait une fonctionnalité qui prend directement en charge l’écriture de code d’initialisation pour l’assembly (techniquement, le module), elle n’est pas exposée en C#. Il s’agit d’un scénario plutôt niche, mais une fois que vous l’avez couru, les solutions semblent être assez douloureuses. Il existe des rapports d’un certain nombre de clients (à l’intérieur et à l’extérieur de Microsoft) qui rencontrent le problème, et il n’y a aucun doute plus de cas non documentés.
Motivation
- Permettre aux bibliothèques d’effectuer une initialisation rapide et rapide lors du chargement, avec une surcharge minimale et sans que l’utilisateur n’a besoin d’appeler explicitement quoi que ce soit
- Un point de douleur particulier des approches actuelles
static
du constructeur est que le runtime doit effectuer des vérifications supplémentaires sur l’utilisation d’un type avec un constructeur statique, afin de décider si le constructeur statique doit être exécuté ou non. Cela ajoute une surcharge mesurable. - Permettre aux générateurs sources d’exécuter une logique d’initialisation globale sans que l’utilisateur ait besoin d’appeler explicitement quoi que ce soit
Conception détaillée
Une méthode peut être désignée comme initialiseur de module en la décorant avec un [ModuleInitializer]
attribut.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
L’attribut peut être utilisé comme suit :
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Certaines exigences sont imposées à la méthode ciblée avec cet attribut :
- La méthode doit être
static
. - La méthode doit être sans paramètre.
- La méthode doit retourner
void
. - La méthode ne doit pas être générique ou être contenue dans un type générique.
- La méthode doit être accessible à partir du module conteneur.
- Cela signifie que l’accessibilité effective de la méthode doit être
internal
oupublic
. - Cela signifie également que la méthode ne peut pas être une fonction locale.
- Cela signifie que l’accessibilité effective de la méthode doit être
Lorsqu’une ou plusieurs méthodes valides avec cet attribut sont trouvées dans une compilation, le compilateur émet un initialiseur de module qui appelle chacune des méthodes attribuées. Les appels seront émis dans un ordre réservé, mais déterministe.
Inconvénients
Pourquoi ne devrions-nous pas le faire ?
- Peut-être que les outils tiers existants pour les initialiseurs de module « injecter » sont suffisants pour les utilisateurs qui demandent cette fonctionnalité.
Concevoir des réunions
8 avril 2020
C# feature specifications