19

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:

  • I want to allow the static class to be explicitly initialized (likely by using a public Initialize() method).
  • I don't want to have to access any other public methods or properties on the class when I don't need them, even though this would initialize the static class.
  • If the class has not been explicitly initialized, I still want to initialize it when it is first needed (i.e. when accessing other public methods or properties with the intent of using the functionality or data they provide).
  • This is a helper class and using the Singleton design pattern is not necessary for my purposes.

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#.

Bernard
  • 7,908
  • 2
  • 36
  • 33
  • Why not initialize the class in the static constructor? I find the your desire to be able to manually initialize unnecessary. – ChaosPandion Jan 05 '12 at 19:28
  • http://msdn.microsoft.com/en-us/library/bb397680.aspx – Venki Jan 05 '12 at 19:29
  • Isn't an "initializable" static class *not* a static class? What would be the purpose for this sort of behavior? It seems that you want to instantiate a class based off static values instead. – Jeremy Holovacs Jan 05 '12 at 19:30
  • @Jeremy Holovacs: By initializing the static class I mean initializing all of its static members. The class is used as a helper class and I have no need to maintain an actual instance of it. – Bernard Jan 05 '12 at 19:42
  • @Ramhound, please point me to how to make a null static class... it seems to me that would be a contradiction in terms. – Jeremy Holovacs Jan 05 '12 at 19:43
  • @Bernard, if you're just after initializing the static members, why not make them static properties in a regular class, and update them as necessary? – Jeremy Holovacs Jan 05 '12 at 19:46
  • @Jeremy Holovacs: As I mentioned at the beginning, the initialization takes about 10-15 seconds. I want to hide these initialization details from anyone using the helper class. I have public static properties to expose values, but not to set them. This is intentional as this helper class serves to wrap around functionality provided by third-party libraries. – Bernard Jan 05 '12 at 19:53
  • @SecurityHound "Just because a class is static doesn't mean it cannot be null. If the class is an object, one would assume the intial value is null, until the class is intialized. " -- That's about as wrong as it's possible to be. – Jim Balter Jan 26 '18 at 19:35

5 Answers5

23

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.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
  • Interesting approach. It's not what I would like to use, but it's good to know that it's an option. – Bernard Jan 05 '12 at 19:36
18

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.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • How can I determine whether the static class is already initialized? I'm not using the Singleton pattern, so I don't have an instance of the class to reference. The static constructor is always called before the body of the `Initialize()` method, so the static members are always initialized. I don't see how I can do this without using the Singleton pattern. – Bernard Jan 05 '12 at 20:14
  • 1
    @Bernard: You'd keep a static variable to say whether `Initialize` had been called first. Note the "via another Initialize" call part - only `Initialize` would set the value, but the static constructor would *test* whether it was already set. – Jon Skeet Jan 05 '12 at 20:33
4

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

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • I am concerned whether your first solution may invoke race condition where initialization of members are done repeatedly. Why not just add an empty static `Initialize()` method, which will get to invoke static constructor any way? – Smart Humanism Oct 13 '22 at 07:04
  • 1
    Thanks @SmartHumanism, that's a great point. Tested and in fact initialize does get called twice. Ctor probably always fires first, so maybe not a race-condition, but definitely unnecessary if calling *any* member whatsoever will force construction in the first place. Updated the answer with your suggestion. – KyleMit Oct 14 '22 at 17:05
2

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()

user1231231412
  • 1,659
  • 2
  • 26
  • 42
  • 1
    I realize that a static constructor cannot be called explicitly, but I want to allow a mechanism to the class to say, "Yes, I want this class to be initialized now!" while still allowing, "I haven't initialized you, but please initialize yourself right before I start using you." – Bernard Jan 05 '12 at 19:35
  • Using the Singleton pattern would force the use of an `Initialize()` method since you need to explicitly create the single instance of the class. I just feel I don't need to maintain an instance of this class because I use this class as a helper class and have no need to pass an instance of it around as an argument to other class methods. – Bernard Jan 05 '12 at 19:39
2

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?

Corey Kosak
  • 2,615
  • 17
  • 13
  • 2
    Not really. I never thought I would design a class with a `Touch()` method. Feels dirty. :) – Bernard Jan 05 '12 at 20:15
  • I wonder if typing `var type = typeof(ClassToInitialize);` would be enough, though I dunno if it'd be compiled away. – Hatchling Feb 25 '17 at 23:27