The module initializers feature for C# 9 enables a new attribute, [ModuleInitializer], to be applied to any number of static methods in a compilation. The marked methods are guaranteed to run before any other method is invoked or field is accessed in the whole module.
Usage example:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M()
{
// This code runs before any other code in the module
}
}
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
Module initializer methods (methods marked with [ModuleInitializer]) must be:
If any methods match these criteria, a module initializer (runtime term for <Module>..cctor) is emitted. This is a special static constructor that has additional runtime guarantees. It will execute before any other field access or method invocation within the entire module. The emitted body is a series of call instructions, one to each module initializer method in a deterministic but undefined order, followed by a ret instruction.
The VB strategy has not been determined. It would either behave the same way or error when System.Runtime.CompilerServices.ModuleInitializerAttribute is applied to a method.
Language proposal (credit to @RikkiGibson) with link to meeting notes:
https://github.com/dotnet/csharplang/blob/master/proposals/module-initializers.md
Compiler feature doc (credit to @RikkiGibson):
https://github.com/dotnet/roslyn/blob/mi-feature-doc/docs/features/module-initializers.md
Runtime spec: https://github.com/dotnet/runtime/blob/master/docs/design/specs/Ecma-335-Augments.md#module-initializer
Test plan umbrella: https://github.com/dotnet/roslyn/issues/40500
Implementation underway: https://github.com/dotnet/roslyn/commits/features/module-initializers
I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.
@GrabYourPitchforks what does the "blocking" label signify here?
It puts this issue to the front of the api-ready-for-review queue. The API Review meetings first review API requests that are labeled "blocking" before reviewing other requests.
@jaredpar presumably this feature won't have language syntax. Normally we don't use System.Runtime.CompilerServices for stuff that developers are expected to use directly. Normally, the namespace is for stuff the compiler generates calls for. However, in this case it seems on par with other very advanced features that we don't want the general public to use, so this feels OK.
C#
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute
{
}
}
What are next steps? Are we ready to open a PR to dotnet/runtime to add the API?
Yeah this is meant for really advanced users, not main stream use hence this namespace feels fine to me.
@RikkiGibson
What are next steps? Are we ready to open a PR to dotnet/runtime to add the API?
That is probably the easiest solution. You could ask @danmosemsft for a dev but attributes are basically trivial.
You can use https://github.com/dotnet/runtime/pull/454 as a template.
We'd planned on having @RikkiGibson do the work here so we'll get a PR out soon-ish for this.
Most helpful comment
Video
@jaredpar presumably this feature won't have language syntax. Normally we don't use
System.Runtime.CompilerServicesfor stuff that developers are expected to use directly. Normally, the namespace is for stuff the compiler generates calls for. However, in this case it seems on par with other very advanced features that we don't want the general public to use, so this feels OK.C# namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class ModuleInitializerAttribute : Attribute { } }