Bernard
Bernard

Reputation: 7961

How to initialize a C# static class before it is actually needed?

I have a static class with a static constructor that takes some time (10-15 seconds) to execute and fully initialize the class. In order to improve performance, I've decided to enable this static class to be explicitly initialized instead of when it is first needed so that it is ready to go when it actually needs to be used.

My first thought was to create an Initialize() method for the class, but since I already have a static constructor, this method doesn't seem to need to do anything other than be the method to call to explicitly initialize the class without accessing any of its other public methods or properties. Having a method that does nothing directly doesn't seem right to me.

Then I thought I can just move the code from the static constructor into this Initialize() method, but I'd also like the class to be initialized when it is first needed and the Initialize() method wasn't explicitly called.

To summarize, I want the following criteria to be observed:

What would be the proper way to observe the above criteria for a static class written in C#? This can also apply to other programming languages (e.g. Java), but I'm personally interested in a solution written in C#.

Upvotes: 19

Views: 27567

Answers (5)

KyleMit
KyleMit

Reputation: 30107

Simply calling any member on the class will force the constructor to run, so you could just get an existing property for example like this:

// trigger static initialization
var _ = StaticClass.MyProperty;

To make the code a little more self documenting, you could add an empty, parameterless, void method called something like Initialize so the code reads with a little more intentionality.

public static class StaticClass
{
    static StaticClass()
    {
       // any logic you want in the constructor
    }

    /// <summary> Blank Method which will force constructor of static class </summary>
    public static void Initialize() { }
}

Then you can call during startup like this:

StaticClass.Initialize();

Demo in .NET Fiddle

See Also: Is the order of static class initialization in C# deterministic?

Update: I had previously suggested putting startup logic in the Initialize method, and also calling from the ctor, but, as Smart Humanism pointed out, this will result in a race condition where Initialize is called twice

Upvotes: 5

vcsjones
vcsjones

Reputation: 141678

I would go with the initialize method (EDIT: See Jon's answer). But if you really just want to use the constructor, you can do this:

var type = typeof (YourType);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

RunClassConstructor allows you to force the class constructor (static constructor) to run if it already hasn't. If it has already run, say because you used a static member of the class, then this has no effect. Running it additional times has no effect.

Upvotes: 24

Corey Kosak
Corey Kosak

Reputation: 2625

The approach doesn't seem icky to me. I might name the method Touch(), give it an empty body, and add an appropriate comment. Would that be sufficient to get you over your feeling that something doesn't feel right about this?

Upvotes: 2

user1231231412
user1231231412

Reputation: 1659

I'm not sure if you can specify when a static constructor is loaded.

From MSDN "A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced."

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx

*EDIT: * Would adding the singleton pattern help here? The getter can call Initialize() by checking a flag in the class, IsLoaded=true. Subsequent calls will not call Initialize()

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502446

I would probably just go for the Initialize method - and it can do something useful:

  • It can log that you're explicitly trying to initialize the class, with a stack trace
  • It might throw an exception if the class is already initialized via another Initialize call
  • You could possibly (with a bit of effort and reorganization) sort things so that any exceptions caused during initialization were propagated without the TypeInitializationException which you'd normally get.

Upvotes: 18

Related Questions