Child static constructor not called when base member accessed

The problem lies in your assumptions about when a static constructor is called. The documentation, which isn't the clearest, states that

It is called automatically before the first instance is created or any static members are referenced.

You may assume that if you call

Node.Load();

that you are calling a static method on the Node class, but in fact you're calling it on the base class, as that is where it is implemented.

So, to fix this, you have two choices. First, you can trigger the static constructor explicitly by creating a new instance of the Node class prior to calling Load()

var foo = new Node(); // static ctor triggered
Node.Load();

or create a protected virtual member that the base class can call in order to get the query value (can't use abstract here, unfortunately)

public class DatabaseEntity<T> where T : Derp {
    protected abstract string Query { get; }
    public static IList<T> Load() {        
        return Database.Get(new DatabaseEntity<T>().Query);
    }
}

Both of which are hacky. Better to dispense with the statics altogether and go with instance methods. Statics should be used sparingly, as they result in tight coupling and other design headaches such as this.


You can also call class constructors directly using System.Runtime.CompilerServices and the RuntimeHelpers type by doing something as follows: RuntimeHelpers.RunClassConstructor(type.TypeHandle);

So for example you could use reflection to loop over all types in an inheritance chain and call each of the static constructors.


Yes, static constructors will not be called till the members of the class is first accessed or first instance is created.

In your case you're accessing DatabaseEntity<T>.Load, so static constructor of DatabaseEntity<T> will be called not its derived class ones.

Even though you call Node.Load it is mapped to DatabaseEntity<Node> at compile time. So technically you're not accessing Node class at all.

Tags:

C#

Wpf