Module-initialisatoren
Notitie
Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.
Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante LDM-notities (Language Design Meeting).
Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.
Kampioenprobleem: https://github.com/dotnet/csharplang/issues/2608
Samenvatting
Hoewel het .NET-platform een functie heeft die rechtstreeks ondersteuning biedt voor het schrijven van initialisatiecode voor de assembly (technisch gezien de module), wordt het niet weergegeven in C#. Dit is een eerder nichescenario, maar zodra je het tegenkomt, lijken de oplossingen behoorlijk pijnlijk te zijn. Er zijn rapporten van een aantal klanten (binnen en buiten Microsoft) die last hebben van het probleem, en er zijn ongetwijfeld meer niet-gedocumenteerde gevallen.
Motivatie
- Stel bibliotheken in staat om gretige, eenmalige initialisatie uit te voeren wanneer deze wordt geladen, met minimale overhead en zonder dat de gebruiker expliciet iets hoeft aan te roepen
- Een bepaald pijnpunt van de huidige
static
constructorbenaderingen is dat de runtime aanvullende controles moet uitvoeren op het gebruik van een type met een statische constructor om te bepalen of de statische constructor moet worden uitgevoerd of niet. Dit voegt meetbare overhead toe. - Brongeneratoren inschakelen om een globale initialisatielogica uit te voeren zonder dat de gebruiker expliciet iets hoeft aan te roepen
Gedetailleerd ontwerp
Een methode kan worden aangewezen als een module-initialisatiefunctie door deze te decoreren met een [ModuleInitializer]
kenmerk.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
Het kenmerk kan als volgt worden gebruikt:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Sommige vereisten worden opgelegd aan de methode die is gericht op dit kenmerk:
- De methode moet
static
zijn. - De methode moet parameterloos zijn.
- De methode moet
void
retourneren. - De methode mag niet algemeen zijn of in een algemeen type zijn opgenomen.
- De methode moet toegankelijk zijn vanuit de insluitingsmodule.
- Dit betekent dat de effectieve toegankelijkheid van de methode
internal
ofpublic
moet zijn. - Dit betekent ook dat de methode geen lokale functie kan zijn.
- Dit betekent dat de effectieve toegankelijkheid van de methode
Wanneer een of meer geldige methoden met dit kenmerk worden gevonden in een compilatie, verzendt de compiler een module-initialisatiefunctie die elk van de toegewezen methoden aanroept. De aanroepen worden verzonden in een gereserveerde, maar deterministische volgorde.
Nadelen
Waarom zouden we dit niet doen?
- Misschien is de bestaande hulpprogramma's van derden voor initialisatiefuncties van modules voldoende voor gebruikers die om deze functie hebben gevraagd.
Ontwerpvergaderingen
8 april 2020
C# feature specifications