56

I'd like to execute the static constructor of a class (i.e. I want to "load" the class) without creating an instance. How do I do that?

Bonus question: Are there any differences between .NET 4 and older versions?

Edit:

  • The class is not static.
  • I want to run it before creating instances because it takes a while to run, and I'd like to avoid this delay at first access.
  • The static ctor initializes private static readonly fields thus cannot be run in a method instead.
mafu
  • 31,798
  • 42
  • 154
  • 247

10 Answers10

129

The other answers are excellent, but if you need to force a class constructor to run without having a reference to the type (i.e. reflection), you can use RunClassConstructor:

Type type = ...;
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Gary Linscott
  • 1,461
  • 2
  • 9
  • 4
  • Does that run the _static_ ctor? The class does not have a public constructor. Also, is this safe in that it does not cause a ctor to run twice, possibly? – mafu Apr 16 '10 at 16:49
  • 6
    Yes, it runs the static ctor. It is also safe, the CLR will only let the static ctor be executed once. – Gary Linscott Apr 16 '10 at 16:54
  • 3
    Indeed, this method is explicitly provided for compiler writers to ensure deterministic initialization: http://blogs.msdn.com/cbrumme/archive/2003/04/15/51348.aspx – Ruben Apr 16 '10 at 17:01
  • Interesting. But cbrumme does not seem to explicitly state that the cctor gets called executed once, or did I miss that? I do like this solution, but I'd like to get this guaranteed before I accept. – mafu Apr 17 '10 at 13:43
  • Thank You! This answer provided the only way for me to solve my problem. I am implementing a Java-like enum pattern using abstract Enumeration class. It has a collection called values which stores a list of all enumerated instances of the derived enumeration class. The collection is inherited by each deriving class, so each derived class has an accessible list of it's enumerated values. Also neat is that the derived class does not need to explicitly handle any of this because the values list is retrieved by a static property in Enumeration class. The only issue I had was this. Solved! – tomosius Mar 19 '16 at 00:51
  • 4
    @tomosius Yes, this solution is correctly marked as such by the OP. The existing [ECMA-335](https://en.wikipedia.org/wiki/Common_Language_Infrastructure) design is essentially *necessary* because finding a workable topological sort for the (possibly cyclic) graph of dependencies entailed by static constructors alone ("type initializers" in .NET-speak) is expensive at best and provably impossible at worst. Since that graph, being entirely disjoint from the proper type hierarchy in .NET, is obscurely specific, the whole enterprise is justifiably judged “not worth it.” – Glenn Slayden Dec 22 '17 at 04:47
  • 1
    @mafu `RunClassConstructor` is a [nop](https://en.wikipedia.org/wiki/NOP) if the class initializer has already been invoked. Otherwise, calling that helper counts as the "one-and-only" invocation. It's exactly what you requested in your question. Do note that the discrepancies I document in [my answer](/a/47934827/147511) (which address your "bonus" inquiry) may still apply, unless you can be sure that you are able to explicitly invoke `RunClassConstructor` before those problems have an opportunity to arise. – Glenn Slayden Dec 22 '17 at 04:54
  • To summarize, the best way to avoid problems is to call `RuntimeHelpers.​RunClass­Construc­tor(t.TypeHandle)` as eagerly, liberally, *and/or* often as you like. It's the only way to (attempt to) explicitly control inter-Type dependencies (via sequencing), and always guarantee that no `Type` initializer will ever be called more than once. This includes properly handling cyclical cases, such a `Type` explicitly requesting—or implicitly demanding—("re-")initialization within the execution scope of of its own initialization (*i.e.*, before its static constructor has exited). – Glenn Slayden Nov 23 '18 at 22:35
  • My previous comment entails that as far as the CLR is concerned, a `Type` is considered initialized at the ***beginning*** of its initializer method body. That is, it's already "initialized" immediately prior to executing the first line of its static constructor. Since a type initializer can call static methods on its own type—and/or exterior methods that do the same—that entire call-graph is excluded from the stronger guarantee that *all* calls into a type's static methods will always see it "fully-initialized," i.e., where the execution scope of the static constructor has ***ended/exited***. – Glenn Slayden Nov 23 '18 at 23:52
  • I found [this answer](https://stackoverflow.com/a/51758748/41236) to be the one I used because it allowed me to re-execute the constructor even if it was executed before, and that was needed because an static class was being used in several tests and the initialization used ConfigurationManager to set a value, only one test needed to reset that vale but not the others. – Eugenio Miró Sep 19 '20 at 13:01
19

Just reference one of your static fields. This will force your static initialization code to run. For example:

public class MyClass
{
    private static readonly int someStaticField;

    static MyClass() => someStaticField = 1;

    // any no-op method call accepting your object will do fine
    public static void TouchMe() => GC.KeepAlive(someStaticField);
}

Usage:

// initialize statics
MyClass.TouchMe();
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Fábio Batista
  • 25,002
  • 3
  • 56
  • 68
7

Also you can do this:

type.TypeInitializer.Invoke(null, null);
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
zumalifeguard
  • 8,648
  • 5
  • 43
  • 56
  • Nice; who knew?!! I wonder how the overall performance of this compares to `RuntimeHelpers.RunClassConstructor`... – Glenn Slayden Jun 27 '19 at 05:02
  • 2
    Note that `TypeInitializer.Invoke` will allow multiple calls to the static constructor, whereas `RuntimeHelpers.RunClassConstructor` guards against that. – Wai Ha Lee Mar 24 '20 at 08:54
  • 1
    This was the solution I was looking for so I can reconfigure an static class when setting a configuration value on a test, nice catch! – Eugenio Miró Sep 19 '20 at 04:41
  • Warning! In addition to allowing you to **re**-invoke the static constructor (yay!) it also allows for the possibility of ending up with NESTED invocations of that static constructor (=:0) which is prevented if you use `RunClassConstructor` or allow the RunTime to initialise it for you. For safety you might want to consider a `Reset()` method that calls `RunClassConstructor()` and *then* `TypeInitializer.Invoke()`, in order to get something that will always re-run it cleanly, whether or not it's run previously. – Brondahl Jan 02 '21 at 12:14
6

The cctor (static constructor) will be called whenever one of the following occurs;

  1. You create an instance of the class
  2. Any static member is accessed
  3. Any time before that, if BeforeFieldInit is set

If you want to explicitly invoke the cctor, assuming you have other static members, just invoke/access them.

If you are not doing anything very interesting in your cctor, the compiler may decide to mark it BeforeFieldInit, which will allow the CLR the option to execute the cctor early. This is explained in more detail here: http://blogs.msdn.com/davidnotario/archive/2005/02/08/369593.aspx

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
csauve
  • 5,904
  • 9
  • 40
  • 50
4

Extending Fábio's observations, the following short and complete test program exposes the JIT-sensitive details of TypeAttributes.BeforeFieldInit behavior, comparing .NET 3.5 to the latest version (as of late 2017) .NET 4.7.1, and also demonstrates the potential hazards for build type variations within each version itself.[1]

using System;
using System.Diagnostics;

class MyClass
{
    public static Object _field = Program.init();

    public static void TouchMe() { }
};

class Program
{
    static String methodcall, fieldinit;

    public static Object init() { return fieldinit = "fieldinit"; }

    static void Main(String[] args)
    {
        if (args.Length != 0)
        {
            methodcall = "TouchMe";
            MyClass.TouchMe();
        }
        Console.WriteLine("{0,18}  {1,7}  {2}", clrver(), methodcall, fieldinit);
    }
};

Below is the console output from running this program in all combinations of { x86, x64 } and { Debug, Release }. I manually added a delta symbol Δ (not emitted by the program) to highlight the differences between the two .NET versions.

.NET 2.0/3.5

2.0.50727.8825 x86 Debug
2.0.50727.8825 x86 Debug TouchMe fieldinit
2.0.50727.8825 x86 Release fieldinit
2.0.50727.8825 x86 Release TouchMe fieldinit
2.0.50727.8825 x64 Debug
2.0.50727.8825 x64 Debug TouchMe fieldinit
2.0.50727.8825 x64 Release
2.0.50727.8825 x64 Release TouchMe fieldinit

.NET 4.7.1

4.7.2556.0 x86 Debug
4.7.2556.0 x86 Debug TouchMe fieldinit
4.7.2556.0 x86 Release Δ
4.7.2556.0 x86 Release TouchMe Δ
4.7.2556.0 x64 Debug
4.7.2556.0 x64 Debug TouchMe fieldinit
4.7.2556.0 x64 Release
4.7.2556.0 x64 Release TouchMe Δ

As noted in the intro, perhaps more interesting than the version 2.0/3.5 versus 4.7 deltas are the differences within the current .NET version, since they show that, although the field-initialization behavior nowadays is more consistent between x86 and x64 than it used to be, it's still possible to experience a significant difference in runtime field initialization behavior between your Debug and Release builds today.

The semantics will depend on whether you happen to call a disjoint or seemingly unrelated static method on the class or not, so if doing so introduces a bug for your overall design, it is likely to be quite mysterious and difficult to track down.


Notes
1. The above program uses the following utility function to display the current CLR version:

static String clrver()
{
    var s = typeof(Uri).Assembly.Location;
    return FileVersionInfo.GetVersionInfo(s).ProductVersion.PadRight(14) +
        (IntPtr.Size == 4 ? " x86 " : " x64 ") +
#if DEBUG
        "Debug  ";
#else
        "Release";
#endif
}
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
2

Static constructors are NOT always called when accessing a static method!

I noticed that if you call a static method in a base class, the static constructor of the super class is NOT called. This unexpected behavior has bitten many times.

ScottK
  • 21
  • 1
  • I'm a bit confused. Suppose you have two derived classes (with static ctors) and call a static method in the base class (which also has a static ctor). The static ctor of which derived class should be called then? Given this reasoning, the behavior you describe sounds not strange. – mafu Jan 02 '17 at 01:07
  • 1
    @mafu I think he's talking about the reverse situation: it is true that any invocation of a `static _ctor` ("type initializer") of some *derived* class in no way entails the invocation of the type initializer of its *base* class, and this may seem counterintuitive at casual first glance. Knowing more about the .NET, CTS, and CIL design and capabilities quickly dispels the intuition, however, and it becomes natural to understand the existing behavior... mainly because it becomes easy to imagine the out-of-control edge cases if it were otherwise! – Glenn Slayden Dec 21 '17 at 23:01
-1

There is no need to do this, the whole point of a static constructor is that it runs once when the class is first initialised at first access. If you want to run something on demand, then consider adding your initialisation code into a public method that is called by the constructor. You can then call this method whenever you like. But I'm not sure why you would want to do this?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Dan Diplo
  • 25,076
  • 4
  • 67
  • 89
  • This fails in my case because there are `static readonly` fields. – mafu Apr 16 '10 at 15:17
  • Your answer is the same as @Ray's but his posted a couple minutes earlier. Unfortunately, like his, your info is also misleading. Besides the problem mentioned in the previous (OP's) comment, the second part of your proposal wouldn't work for `static class MyClass { }` (which had been available since 2006 at that point). – Glenn Slayden Dec 21 '17 at 21:10
-1

As others have said, static constructors run automatically. If you need to be explicit, maybe you should refactor it into a static method which you can run explicitly?

Explicitly calling a static method would also, of course, ensure that the static constructor had been executed.

edit

Static constructors are run when any static members are referenced. You could simply create a dummy method called initialize which did nothing but ensure that the framework calls the static constructor.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Gabe Moothart
  • 31,211
  • 14
  • 77
  • 99
-1

I'm not exactly sure what your use case is for this, but you can force static initializers to run in a fairly hacky way using partial classes and inner classes:

The idea is to use a partial outter class with a static field that accesses another static field on the inner class. When the outter class is statically initialized, the static field initialization will kick-off the static initialization of all the inner classes:


public partial class OutterClass
{
    // When OutterClass is initialized, this will force InnerClass1 to be initialized.
    private static int _innerClass1Touched = InnerClass1.TouchMe;

    public static class InnerClass1
    {
        public static int TouchMe = 0;

        static InnerClass1()
        {
            Console.WriteLine("InnerClassInitialized");
        }
    }
}

public partial class OutterClass
{
    // When OutterClass is initialized, this will force InnerClass2 to be initialized.
    private static int _innerClass2Touched = InnerClass2.TouchMe;

    public static class InnerClass2
    {
        public static int TouchMe = 0;

        static InnerClass2()
        {
            Console.WriteLine("InnerClass2Initialized");
        }
    }
}

Then, somewhere early in your application, you just need to reference OutterClass in a way that will result in static initialization, like constructing an instance of it.

A more realistic example might be...

public interface IService
{
    void SayHello();
}

public partial class ServiceRegistry
{
    private static List<Func<IService>> _serviceFactories;

    private static void RegisterServiceFactory(Func<IService> serviceFactory)
    {
        // This has to be lazily initialized, because the order of static initialization
        //  isn't defined. RegisterServiceFactory could be called before _serviceFactories
        //  is initialized.
        if (_serviceFactories == null)
            _serviceFactories = new List<Func<IService>>();

        _serviceFactories.Add(serviceFactory);
    }

    public List<IService> Services { get; private set; }

    public ServiceRegistry()
    {
        Services = new List<IService>();

        foreach (var serviceFactory in _serviceFactories)
        {
            Services.Add(serviceFactory());
        }
    }
}


// In another file (ServiceOne.cs):
public class ServiceOne : IService
{
    void IService.SayHello()
    {
        Console.WriteLine("Hello from ServiceOne");
    }
}

public partial class ServiceRegistry
{
    // When OutterClass is initialized, this will force InnerClass1 to be initialized.
    private static int _serviceOneRegistryInitializer = ServiceOneRegistry.Initialize;

    private static class ServiceOneRegistry
    {
        public static int Initialize = 0;

        static ServiceOneRegistry()
        {
            ServiceRegistry.RegisterServiceFactory(() => new ServiceOne());
        }
    }
}

// In another file (ServiceTwo.cs):
public class ServiceTwo : IService
{
    void IService.SayHello()
    {
        Console.WriteLine("Hello from ServiceTwo");
    }
}

public partial class ServiceRegistry
{
    // When OutterClass is initialized, this will force InnerClass1 to be initialized.
    private static int _serviceTwoRegistryInitializer = ServiceTwoRegistry.Initialize;

    private static class ServiceTwoRegistry
    {
        public static int Initialize = 0;

        static ServiceTwoRegistry()
        {
            ServiceRegistry.RegisterServiceFactory(() => new ServiceTwo());
        }
    }
}

static void Main(string[] args)
{
    ServiceRegistry registry = new ServiceRegistry();
    foreach (var service in registry.Services)
    {
        serivce.SayHello();
    }

    // Output will be:
    // Hello from ServiceOne
    // Hello from ServiceTwo

    // No guarantee on order.
}

Why even do this? It has a very narrow use-case. It eliminates the need to have a single method that initializes and registers all the services. The case in which I personally want to eliminate that single method initialization is for code generation purposes.

-4

The static constructor runs automatically the first time you access the class. There is no need (or capability) to 'run' it yourself.

Ray
  • 21,485
  • 5
  • 48
  • 64
  • 4
    Not *quite* true... it can run later: http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0.aspx – Marc Gravell Apr 16 '10 at 15:15
  • 8
    I am constantly amazed by the number of obscure language features which I have never heard of, will probably never intentionally use, but which will probably bite me in the ass because I am not aware of them... – Ray Apr 16 '10 at 15:23
  • I want to run it earlier because it takes a long time (see edited question). – mafu Apr 16 '10 at 15:28
  • makes sense - create a "load()" method on your static class and call it whenever you want to. Just be sure to using locking and flags (or whatever) if necessary so it doesn't get loaded multiple times. – Ray Apr 16 '10 at 15:36
  • 1
    @Ray: A load method can't initialize readonly fields though. :\ – mafu Apr 16 '10 at 15:39
  • As Mick Jagger once said: "you can't always git what you want" - how about using private static members with public static 'get' properties? – Ray Apr 16 '10 at 15:42
  • @Ray: Possible workaround, but I specifically asked this question because I wanted to avoid that. – mafu Apr 16 '10 at 15:50
  • 1
    Cool - I like Fabio's no-op method idea. Reading any property (even to throw away the value) would work too. – Ray Apr 16 '10 at 15:56
  • @Ray To avoid further downvotes, please add a prominent warning or amendment to the text of this answer to clarify that it contains an incorrect assertion. – Glenn Slayden Dec 21 '17 at 21:02
  • 1
    Marc Gravell's link is now dead and can be found on Jon Skeet's site here: https://codeblog.jonskeet.uk/2010/01/26/type-initialization-changes-in-net-4-0/ – Wai Ha Lee Mar 24 '20 at 08:40