Dela via


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:

  1. Metoden måste vara static.
  2. Metoden måste vara parameterlös.
  3. Metoden måste returnera void.
  4. Metoden får inte vara generisk eller finnas i en generisk typ.
  5. Metoden måste vara tillgänglig från den innehållande modulen.
    • Det innebär att metodens effektiva tillgänglighet måste vara internal eller public.
    • Det innebär också att metoden inte kan vara en lokal funktion.

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