3 KiB
Module Initializers
- Proposed
- Prototype: In Progress
- Implementation: In Progress
- Specification: Not Started
Summary
Although the .NET platform has a feature that directly supports writing initialization code for the assembly (technically, the module), it is not exposed in C#. This is a rather niche scenario, but once you run into it the solutions appear to be pretty painful. There are reports of a number of customers (inside and outside Microsoft) struggling with the problem, and there are no doubt more undocumented cases.
Motivation
- Enable libraries to do eager, one-time initialization when loaded, with minimal overhead and without the user needing to explicitly call anything
- One particular pain point of current
static
constructor approaches is that the runtime must do additional checks on usage of a type with a static constructor, in order to decide whether the static constructor needs to be run or not. This adds measurable overhead. - Enable source generators to run some global initialization logic without the user needing to explicitly call anything
Detailed design
A method can be designated as a module initializer by decorating it with a [ModuleInitializer]
attribute.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
The attribute can be used like this:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Some requirements are imposed on the method targeted with this attribute:
- The method must be
static
. - The method must be parameterless.
- The method must return
void
. - The method must not be generic or be contained in a generic type.
- The method must be accessible from the containing module.
- This means the method's effective accessibility must be
internal
orpublic
. - This also means the method cannot be a local function.
- This means the method's effective accessibility must be
When one or more valid methods with this attribute are found in a compilation, the compiler will emit a module initializer which calls each of the attributed methods. The calls will be emitted in a reserved, but deterministic order.
Drawbacks
Why should we not do this?
- Perhaps the existing third-party tooling for "injecting" module initializers is sufficient for users who have been asking for this feature.