为什么我的静态构造函数不被调用

时间:2014-09-18 02:52:30

标签: c# .net

我有两个类,我试图用来实现字符串枚举模式。问题是当调用父类的操作符时,不会调用子类的静态构造函数。有没有一种方法可以解决这个问题,而无需在代码中添加黑客来初始化静态成员?

public abstract class BaseStringEnum<T> where T : BaseStringEnum<T>
{
    public string Value { get; private set; }

    private static List<T> _values = null;
    protected static List<T> Values 
    {
        get
        {
            if (_values == null)
            {
                _values = new List<T>();
            }

            return _values;
        }
    }

    protected BaseStringEnum(string value, string resId)
    {
        Value = value;
        ResourceId = resId;

        Values.Add((T)this);
    }

    public static implicit operator string(BaseStringEnum<T> value)
    {
        return value.Value;
    }

    public static implicit operator BaseStringEnum<T>(string value)
    {
        return Values.Where(v => v.Value.Trim() == value.Trim()).First();
    }
}


public sealed class UseTimeStringEnum : BaseStringEnum<UseTimeStringEnum>
{
    private UseTimeStringEnum(string value, string resourceId) : base(value, resourceId) { }

    public static readonly UseTimeStringEnum None;// = new UseTimeStringEnum("N", "None");
    public static readonly UseTimeStringEnum Required;// = new UseTimeStringEnum("R", "Required");
    public static readonly UseTimeStringEnum Optional;// = new UseTimeStringEnum("O", "Optional");

    static UseTimeStringEnum()
    {
        None = new UseTimeStringEnum("N", "None");
        Required = new UseTimeStringEnum("R", "Required");
        Optional = new UseTimeStringEnum("O", "Optional");
    }
}

问题是,当代码尝试执行(UseTimeStringEnum)"R"之类的操作时,它失败了,因为静态构造函数还没有被解雇。我觉得应该开火,因为我使用静态操作符。

2 个答案:

答案 0 :(得分:4)

满足以下条件之一时,将调用某个类的静态构造函数:

  1. 创建了类的实例;
  2. 访问该类的任何静态字段。
  3. 由于您没有创建UseTimeStringEnum的实例,因此不会在代码中访问它的静态字段,因此不会调用静态构造函数。

    所以关键是:BaseStringEnum在编译时不知道UseTimeStringEnum。

    我看到唯一合适的解决方案 - 我们可以在运行时引用UseTimeStringEnum。

    我将静态构造函数添加到加载的BaseStringEnum类中,并使用Reflection观察所有可用的子类。

    现在调用静态构造函数。

    编辑:Mykroft指出有一种方法可以直接调用静态构造函数,而不是使用反射引用静态字段。所以我相信最终的代码片段应该是

    static BaseStringEnum()
    {
        var StringEnumTypes = AppDomain.CurrentDomain.GetAssemblies()
              .SelectMany(a => a.GetTypes())
              .Where(type => type.IsSubclassOf(typeof(BaseStringEnum<T>)));
    
        foreach (var type in StringEnumTypes) type.TypeInitializer.Invoke(null, null);
    }
    

答案 1 :(得分:1)

正如其他人正确地指出我的构造函数没有被调用,因为父类不知道子类。幸运的是在this问题中我发现了一段代码片段,它们明确地调用了构造函数。

typeof(T).TypeInitializer.Invoke(null, null); 

这适用于我的目的。