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:
- Metoda musi być
static
. - Metoda musi być bez parametrów.
- Metoda musi zwrócić
void
. - Metoda nie może być ogólna ani nie może być zawarta w typie ogólnym.
- Metoda musi być dostępna z modułu zawierającego.
- Oznacza to, że efektywna dostępność metody musi być
internal
lubpublic
. - Oznacza to również, że metoda nie może być funkcją lokalną.
- Oznacza to, że efektywna dostępność metody musi być
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.
C# feature specifications