Megosztás a következőn keresztül:


Modul inicializálói

Jegyzet

Ez a cikk egy funkcióspecifikáció. A specifikáció a funkció tervezési dokumentumaként szolgál. Tartalmazza a specifikáció javasolt módosításait, valamint a funkció tervezése és fejlesztése során szükséges információkat. Ezeket a cikkeket mindaddig közzéteszik, amíg a javasolt specifikációmódosításokat nem véglegesítik, és be nem építik a jelenlegi ECMA-specifikációba.

A szolgáltatás specifikációja és a befejezett implementáció között eltérések lehetnek. Ezeket a különbségeket a vonatkozó nyelvi tervezési értekezlet (LDM) megjegyzései rögzítik.

A funkcióspektusok C# nyelvi szabványba való bevezetésének folyamatáról a specifikációkcímű cikkben olvashat bővebben.

Bajnoki probléma: https://github.com/dotnet/csharplang/issues/2608

Összefoglalás

Bár a .NET platform rendelkezik egy funkcióval, amely közvetlenül támogatja az inicializálási kód írását a szerelvényhez (technikailag a modulhoz), ez a funkció a C#-ban nincs kitéve vagy elérhető. Ez egy meglehetősen szűk körű forgatókönyv, de miután belefut ebbe, a megoldások meglehetősen fájdalmasnak tűnnek. Vannak jelentések arról, számos ügyfél (a Microsofton belül és kívül) küzd a problémával, és kétségtelenül több nem dokumentált eset is van.

Motiváció

  • Lehetővé teszi a kódtárak számára, hogy igényes, egyszeri inicializálást végezzenek betöltéskor, minimális többletterhelés mellett, és anélkül, hogy a felhasználónak explicit módon kellene meghívnia bármit
  • Az aktuális static konstruktor-megközelítések egyik különleges fájdalompontja, hogy a futtatókörnyezetnek további ellenőrzéseket kell végeznie egy statikus konstruktort használó típus használatán annak eldöntéséhez, hogy a statikus konstruktort futtatni kell-e vagy sem. Ez mérhető többletterhelést ad hozzá.
  • Engedélyezze a forrásgenerátorok számára, hogy globális inicializálási logikát futtasson anélkül, hogy a felhasználónak explicit módon kellene meghívnia bármit

Részletes kialakítás

A metódusok egy [ModuleInitializer] attribútummal történő dekorálásával modul inicializálóként is kijelölhetők.

using System;
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ModuleInitializerAttribute : Attribute { }
}

Az attribútum a következő módon használható:

using System.Runtime.CompilerServices;
class C
{
    [ModuleInitializer]
    internal static void M1()
    {
        // ...
    }
}

Az attribútummal megcélzott metódusra bizonyos követelmények vonatkoznak:

  1. A módszernek statickell lennie.
  2. A metódusnak paraméter nélkülinek kell lennie.
  3. A metódusnak voidkell visszaadnia.
  4. A metódus nem lehet általános, és nem lehet egy általános típus része.
  5. A metódusnak elérhetőnek kell lennie a tartalmazó modulból.
    • Ez azt jelenti, hogy a módszer hatékony hozzáférhetőségének internal vagy publickell lennie.
    • Ez azt is jelenti, hogy a metódus nem lehet helyi függvény.

Ha egy fordításban egy vagy több érvényes metódus található ezzel az attribútummal, a fordító egy modul inicializálót bocsát ki, amely meghívja az egyes attribútumokkal rendelkező metódusokat. A hívások fenntartott, de determinisztikus sorrendben lesznek kibocsátva.

Hátránya

Miért ne csinálni?

  • Talán a "modulinicializálók befecskendezése" meglévő külső eszközkészlete elegendő azoknak a felhasználóknak, akik ezt a funkciót kérték.

Tervezési megbeszélések

2020. április 8-án