访问基本成员时未调用子静态构造函数

Cha*_*s W 9 c# wpf

我有一个类定义为:

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

public class Node : DatabaseEntity<Node> {
    static Node() {
        Node.Query = @"SELECT Id FROM Node";
    }
}
Run Code Online (Sandbox Code Playgroud)

当我Node.Load()从codebehind(Window.xaml.cs)运行时,Node的静态构造函数永远不会触发; 或者至少没有遇到断点,也没有将Node.Query设置为null以外的任何东西.

有什么理由可能会发生这种情况吗?

请查看以下答案以获得一些解决方案.对于我的情况,我决定简单地将Query变量设为public,并将所有实例设置Query在一个地方.(不理想,但它有效.)

小智 5

问题在于您对何时调用静态构造函数的假设。该文件,这是不清晰的,指出

在创建第一个实例或引用任何静态成员之前自动调用它。

你可能会假设如果你打电话

Node.Load();
Run Code Online (Sandbox Code Playgroud)

您正在类上调用静态方法Node,但实际上您是在基类上调用它,因为这是实现它的地方。

因此,要解决此问题,您有两个选择。首先,您可以通过在调用之前创建 Node 类的新实例来显式触发静态构造函数Load()

var foo = new Node(); // static ctor triggered
Node.Load();
Run Code Online (Sandbox Code Playgroud)

或者创建一个受保护的虚拟成员,基类可以调用该成员以获取查询值(不幸的是,这里不能使用抽象)

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

这两个都是hacky。最好完全放弃静态并使用实例方法。应谨慎使用静态,因为它们会导致紧耦合和其他诸如此类的设计难题。