Modulinitierare
Not
Den här artikeln är en funktionsspecifikation. Specifikationen fungerar som designdokument för funktionen. Den innehåller föreslagna specifikationsändringar, tillsammans med information som behövs under utformningen och utvecklingen av funktionen. Dessa artiklar publiceras tills de föreslagna specifikationsändringarna har slutförts och införlivats i den aktuella ECMA-specifikationen.
Det kan finnas vissa skillnader mellan funktionsspecifikationen och den slutförda implementeringen. Dessa skillnader finns dokumenterade i de relevanta anteckningarna från Language Design Meeting .
Du kan läsa mer om processen för att införa funktionsspecifikationer i C#-språkstandarden i artikeln om specifikationerna.
Champion-problem: https://github.com/dotnet/csharplang/issues/2608
Sammanfattning
Även om .NET-plattformen har en funktion som har direkt stöd för att skriva initieringskod för sammansättningen (tekniskt sett modulen), exponeras den inte i C#. Detta är ett ganska nischscenario, men när du stöter på det verkar lösningarna vara ganska smärtsamma. Det finns rapporter om ett antal kunder (inom och utanför Microsoft) som kämpar med problemet, och det finns utan tvivel fler odokumenterade fall.
Motivation
- Möjliggör för bibliotek att utföra snabb initiering en gång när de laddas, med minimala resurser och utan att användaren uttryckligen behöver anropa något
- Ett specifikt problemområde för nuvarande
static
konstruktormetoder är att körningstiden måste utföra ytterligare kontroller av användningen av en typ med en statisk konstruktor, för att avgöra om den statiska konstruktorn behöver köras eller inte. Detta lägger till mätbara omkostnader. - Aktivera källgeneratorer för att köra viss global initieringslogik utan att användaren uttryckligen behöver anropa något
Detaljerad design
En metod kan betecknas som en modulinitierare genom att dekorera den med ett [ModuleInitializer]
attribut.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
Attributet kan användas så här:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Vissa krav ställs på den metod som är riktad mot det här attributet:
- Metoden måste vara
static
. - Metoden måste vara parameterlös.
- Metoden måste returnera
void
. - Metoden får inte vara generisk eller finnas i en generisk typ.
- Metoden måste vara tillgänglig från den innehållande modulen.
- Det innebär att metodens effektiva tillgänglighet måste vara
internal
ellerpublic
. - Det innebär också att metoden inte kan vara en lokal funktion.
- Det innebär att metodens effektiva tillgänglighet måste vara
När en eller flera giltiga metoder med det här attributet hittas i en kompilering genererar kompilatorn en modulinitierare som anropar var och en av de tillskrivna metoderna. Anropen genereras i en reserverad, men deterministisk ordning.
Nackdelar
Varför skulle vi inte göra detta?
- Kanske räcker det befintliga verktyget från tredje part för att "mata in" modulinitierare för användare som har frågat efter den här funktionen.
Designa möten
8 april 2020
C# feature specifications