Explicitly call static constructor

22,099

Solution 1

As I found out today, the static constructor CAN be called directly:

from another Stackoverflow post

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

Type type = ...;
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);  

I had to add this code to my application to work around a possible bug in the .net 4.0 CLR.

Solution 2

For anyone finding this thread and wondering... I just did the test. It appears System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() will only run the static constructor if it has not already been run for another reason.

For example, if your code isn't positive whether or not previous code may have accessed the class and triggered the static constructor to run, it doesn't matter. That previous access will have triggered the static constructor to run, but then RunClassConstructor() will not run it also. RunClassConstructor() only runs the static constructor if it hasn't already been run.

Accessing the class after RunClassConstructor() also does not result in the static constructor being run a second time.

This is based on testing in a Win10 UWP app.

Solution 3

Just add public static void Initialize() { } method to your static class and call it when you want. This is very similar to call constructor, because static constructor will be called automatically.

Solution 4

If you have a static member in your class (there must be, otherwise static constructor wouldn't do too much) then no need to explicitly call the static constructor.

Simply access the class where you would like to call its static constructor. E.g.:

public void MainMethod()
{
    // Here you would like to call the static constructor

    // The first access to the class forces the static constructor to be called.
    object temp1 = MyStaticClass.AnyField;

    // or
    object temp2 = MyClass.AnyStaticField;
}
Share:
22,099
meetjaydeep
Author by

meetjaydeep

Explore

Updated on June 02, 2020

Comments

  • meetjaydeep
    meetjaydeep about 4 years

    I want to write unit test for below class.
    If name is other than "MyEntity" then mgr should be blank.
    Negative Unit test
    Using Manager private accessor I want to change name to "Test" so that mgr should be null. And then will verify the mgr value. To achieve this, I want to explicitly call the static constructor but when I call the static constructor using

    Manager_Accessor.name = "Test"
    typeof(Manager).TypeInitializer.Invoke(null, null); 
    

    name is always set to "MyEntity" how to set name to "Test" and invoke the static constructor.

    public class Manager
    {        
            private static string name= "MyEntity";
    
            private static object mgr;
    
            static Manager()
            {
                try
                {
                    mgr = CreateMgr(name);
                }
                catch (Exception ex)
                {
                    mgr=null;
                }
            }
    }
    
  • Admin
    Admin over 6 years
    That makes me incredibly sad as now whenever I want to reset my static class' values I need to call its static method that does exactly the same thing the constructor does - sets default values.
  • kburgoyne
    kburgoyne over 6 years
    Correct. You're not "constructing" the objects again. Only setting their values. Suppose you had already construction a non-static object and stored references to it in a bunch of different places in your code. Now you want to reset the object's values. You wouldn't reconstruct ("new") the object again. All those old stored references would still be to the old object. Instead you'd have a method which reset the values on the already constructed object. Then you'd realize the constructor and reset methods were doing the same thing, so you'd just called the reset method from the constructor.
  • Brondahl
    Brondahl over 3 years
    see answers on here: stackoverflow.com/a/51758748/1662268 for what to do if you need it to run repeatedly.
  • entiat
    entiat over 2 years
    I think this is the correct answer. It doesn't depend on unspecified (that I can find anyways) RunClassConstructor behavior that it will only execute the static constructor once. Invoking an empty "Initialize()" on the class has behavior specified in the C# language definition that can be relied upon.