Sdílet prostřednictvím


Inicializátory modulů

Poznámka

Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.

Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách schůzce návrhu jazyka (LDM).

Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .

Problém šampiona: https://github.com/dotnet/csharplang/issues/2608

Shrnutí

Ačkoli platforma .NET má vlastnost , která přímo podporuje zápis inicializačního kódu pro sestavení (technicky modul), není v jazyce C# dostupná. Jedná se o poměrně specifický scénář, a jakmile na něj narazíte, řešení se zdají být docela bolestivá. Existují zprávy o řadě zákazníků (uvnitř i mimo Microsoft), kteří se potýkají s tímto problémem, a není pochyb o dalších nezdokumentovaných případech.

Motivace

  • Umožněte knihovnám provést při načítání nadšenou jednorázovou inicializaci s minimální režijní náročností a bez nutnosti, aby uživatel jakkoliv explicitně volal.
  • Jedním z konkrétních problémů současných přístupů konstruktora static je, že modul runtime musí provádět další kontroly použití typu se statickým konstruktorem, aby rozhodl, zda je nutné spustit statický konstruktor. Tím se zvyšuje měřitelná režie.
  • Povolení generátorů kódu ke spuštění určité logiky globální inicializace, aniž by uživatel musel explicitně volat cokoli.

Podrobný návrh

Metodu lze označit jako inicializátor modulu pomocí atributu [ModuleInitializer].

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

Atribut lze použít takto:

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

Pro metodu, na kterou cílí tento atribut, se vztahují některé požadavky:

  1. Metoda musí být static.
  2. Metoda musí být bez parametrů.
  3. Metoda musí vrátit void.
  4. Metoda nesmí být obecná nebo nesmí být obsažena v obecném typu.
  5. Metoda musí být přístupná z obsahujícího modulu.
    • To znamená, že efektivní přístupnost metody musí být internal nebo public.
    • To také znamená, že metoda nemůže být místní funkcí.

Pokud se v kompilaci nachází jedna nebo více platných metod s tímto atributem, kompilátor vygeneruje inicializátor modulu, který volá každou z atributů metod. Volání budou odesílána v předurčeném, ale deterministickém pořadí.

Nevýhody

Proč bychom to neměli?

  • Možná jsou stávající nástroje od třetích stran pro "injekci" inicializátorů modulů dostatečné pro uživatele, kteří tuto funkci požadovali.

Designérské schůzky

8. dubna 2020