Инициализаторы модулей
Заметка
Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Она включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.
Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия фиксируются в соответствующем заседании по проектированию языка (LDM).
Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .
Проблема чемпиона: https://github.com/dotnet/csharplang/issues/2608
Сводка
Хотя платформа .NET имеет функцию , которая напрямую поддерживает написание кода инициализации для сборки (технически, модуль), она недоступна в C#. Это довольно нишевая ситуация, но как только вы сталкиваетесь с ней, решения кажутся довольно болезненными. Существуют сообщения о определенном количестве клиентов, (внутри и за пределами Майкрософт), борющихся с проблемой, и, без сомнений, существуют и другие незадокументированные случаи.
Мотивация
- Предоставьте возможность библиотекам производить предварительную единовременную инициализацию при загрузке с минимальными накладными расходами и без необходимости пользователя явно что-либо вызывать.
- Одна из проблем в текущих подходах к конструктору
static
заключается в том, что среда выполнения должна выполнять дополнительные проверки при использовании типа со статическим конструктором, чтобы решить, нужно ли запускать статический конструктор. Это добавляет измеримые издержки. - Разрешить генераторам исходного кода выполнять логику глобальной инициализации без необходимости явного вызова каких-либо функций пользователем.
Подробный дизайн
Метод можно назначить в качестве инициализатора модуля, декорируя его атрибутом [ModuleInitializer]
.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
Атрибут можно использовать следующим образом:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Некоторые требования применяются к методу, предназначенному для этого атрибута:
- Метод должен быть
static
. - Метод должен быть без параметров.
- Метод должен возвращать
void
. - Метод не должен быть универсальным или содержаться в универсальном типе.
- Метод должен быть доступен из содержащего модуля.
- Это означает, что эффективная доступность метода должна быть
internal
илиpublic
. - Это также означает, что метод не может быть локальной функцией.
- Это означает, что эффективная доступность метода должна быть
Если один или несколько допустимых методов с этим атрибутом найдены в компиляции, компилятор выдает инициализатор модуля, который вызывает каждый из методов атрибутов. Вызовы будут выдаваться в зарезервированном, но детерминированном порядке.
Недостатки
Почему мы должны не делать это?
- Возможно, существующий сторонний инструментарий для "внедрения" инициализаторов модулей является достаточным для пользователей, которые запрашивали эту функцию.
Совещания по дизайну
8 апреля 2020 г.
C# feature specifications