![](/img/trans.png)
[英]When does a static member of a class get accessed before the static constructor of the same class
[英]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.CompilerServices
和RuntimeHelpers
类型调用类构造函数: RuntimeHelpers.RunClassConstructor(type.TypeHandle);
因此,例如,您可以使用反射循环继承链中的所有类型并调用每个静态构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.