Udostępnij za pośrednictwem


Inicjatory modułów

Notatka

Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.

Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są ujęte w odpowiednich notatkach ze spotkań projektowania języka (LDM) .

Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .

Problem z mistrzem: https://github.com/dotnet/csharplang/issues/2608

Streszczenie

Mimo że platforma .NET ma funkcję , która bezpośrednio obsługuje pisanie kodu inicjowania dla zestawu (technicznie, modułu), nie jest uwidoczniona w języku C#. Jest to raczej niszowy scenariusz, ale kiedy się z nim zetkniesz, rozwiązania mogą okazać się dość bolesne. Istnieją raporty o pewnej liczbie klientów (zarówno wewnątrz, jak i poza firmą Microsoft), którzy zmagają się z problemem, a nie ma wątpliwości, że istnieje więcej nieudokumentowanych przypadków.

Motywacja

  • Umożliwiaj bibliotekom szybkie inicjowanie jednorazowe podczas ładowania z minimalnym obciążeniem i bez konieczności jawnego wywoływania niczego przez użytkownika
  • Jednym z problematycznych aspektów obecnego podejścia do konstruktora static jest to, że środowisko uruchomieniowe musi przeprowadzić dodatkowe kontrole użycia typu z konstruktorem statycznym, aby ustalić, czy należy uruchomić konstruktor statyczny. Zwiększa to wymierne obciążenie.
  • Włącz generatory źródeł, aby uruchamiać pewną globalną logikę inicjowania bez konieczności jawnego wywoływania niczego przez użytkownika

Szczegółowy projekt

Metodę można wyznaczyć jako inicjator modułu, dekorując ją za pomocą atrybutu [ModuleInitializer].

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

Atrybut można użyć w następujący sposób:

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

Niektóre wymagania są nakładane na metodę docelową tego atrybutu:

  1. Metoda musi być static.
  2. Metoda musi być bez parametrów.
  3. Metoda musi zwrócić void.
  4. Metoda nie może być ogólna ani nie może być zawarta w typie ogólnym.
  5. Metoda musi być dostępna z modułu zawierającego.
    • Oznacza to, że efektywna dostępność metody musi być internal lub public.
    • Oznacza to również, że metoda nie może być funkcją lokalną.

Gdy w kompilacji znajduje się co najmniej jedna prawidłowa metoda z tym atrybutem, kompilator emituje inicjator modułu, który wywołuje każdą z metod przypisanych. Wywołania będą emitowane w zarezerwowanej kolejności, ale deterministycznej.

Niedogodności

Dlaczego tego nie zrobić?

  • Być może istniejące narzędzia innych firm do „wstrzykiwania” inicjatorów modułów są wystarczające dla użytkowników, którzy prosili o tę funkcję.

Spotkania projektowe

8 kwietnia 2020 r.