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

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

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

为什么会发生这种情况?

解决方案

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

最佳答案

问题在于您对何时调用静态构造函数的假设。 documentation ,这不是最清楚的,指出

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

你可以假设如果你调用

Node.Load();

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

因此,要解决此问题,您有两种选择。首先,您可以通过在调用 Load()

之前创建 Node 类的新实例来显式触发静态构造函数
var foo = new Node(); // static ctor triggered
Node.Load();

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

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。最好完全放弃静态并使用实例方法。静态应该谨慎使用,因为它们会导致紧密耦合和其他设计问题,例如这个。

关于c# - 访问基本成员时未调用子静态构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27487285/

相关文章:

c# - 多层次数据模板

wpf - 限制 slider 文本框小数位数

wpf - WPF 中的焦点数据模板

wpf - MouseOver和MouseDown上的动画按钮

C# 如果在 SQL 更新中可用,否则插入

c# - 递归映射 ExpandoObject

c# - WPF/C# : Is it considered bad practice to put resources in Application and casting Application. 当前访问它们?

c# - 如何为 Dispatcher.BeginInvoke 提供回调函数

c# - list.ToString 没有显示正确的输出

c# - OWIN 停止服务器\服务?