繁体   English   中英

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

[英]Child static constructor not called when base member accessed

我有一个类定义为:

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";
    }
}

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

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

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

是的,在首次访问类的成员或创建第一个实例之前,不会调用静态构造函数。

在您的情况下,您正在访问DatabaseEntity<T>.Load ,因此将调用DatabaseEntity<T>静态构造函数而不是其派生类。

即使您调用Node.Load它也会在编译时映射到DatabaseEntity<Node> 所以从技术上讲,你根本就不会访问Node类。

问题在于您对何时调用静态构造函数的假设。 文档不是最清楚的,表明了这一点

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

你可以假设,如果你打电话

Node.Load();

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

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

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

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

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

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

您还可以通过执行以下操作直接使用System.Runtime.CompilerServicesRuntimeHelpers类型调用类构造函数: RuntimeHelpers.RunClassConstructor(type.TypeHandle);

因此,例如,您可以使用反射循环继承链中的所有类型并调用每个静态构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM