为什么FieldInfo.GetValue(null)在静态构造函数中不起作用

时间:2015-06-24 12:05:32

标签: c# reflection static-constructor

请参阅下面的代码。我想要一个自动枚举其自己类型的所有已定义的静态只读实例的类(请参阅TestClass作为示例,它定义了3个自己类型的静态只读实例)。

我想要这种自动化,因为我希望循环定义的类型,而不是冒险忘记将新实例添加到All列表的风险。

好的,我有它的工作,这不是重点。但是,当从静态构造函数调用时,为什么FillAll不起作用?请参阅DefinedInstancesBase<T>代码中注释的静态构造函数。我的意思是FieldInfo.GetValue(null)在静态构造函数中返回null,尽管调试器已经在调用FieldInfo.GetValue(null)之前创建了静态只读实例。

我很好奇为什么它不起作用。这是设计的吗?

public abstract class DefinedInstancesBase<T>
{
    public static IList<T> All
    {
        get
        {
            if (_All == null)
            {
                FillAll();
            }
            return _All;
        }
    }

    //Why this doesn't work? No idea.
    //static DefinedInstancesBase()
    //{
    //    FillAll();
    //}

    private static void FillAll()
    {
        var typeOfT = typeof(T);
        var fields = typeOfT.GetFields(BindingFlags.Public | BindingFlags.Static);
        var fieldsOfTypeT = fields.Where(f => f.FieldType == typeOfT);
        _All = new List<T>();
        foreach (var fieldOfTypeT in fieldsOfTypeT)
        {
            _All.Add((T)fieldOfTypeT.GetValue(null));
        }
    }

    private static List<T> _All = null;
}

[TestClass]
public class DefinedInstancesTest
{
    [TestMethod]
    public void StaticReadOnlyInstancesAreEnumerated()
    {
        //Given
        var expectedClasses = new List<TestClass>
        {
            TestClass.First,
            TestClass.Second,
            TestClass.Third,
        };

        //When
        var actualClasses = TestClass.All;

        //Then
        for (var i=0; i<expectedClasses.Count; i++)
        {
            Assert.AreEqual(expectedClasses[i].Id, actualClasses[i].Id);
        }
    }

    private class TestClass : DefinedInstancesBase<TestClass>
    {
        public static readonly TestClass First = new TestClass(1);
        public static readonly TestClass Second = new TestClass(2);
        public static readonly TestClass Third = new TestClass(3);

        public int Id { get; private set; }

        private TestClass(int pId)
        {
            Id = pId;
        }
    }
}

1 个答案:

答案 0 :(得分:2)

这里有两个独立的问题。

  1. 上面代码中的static构造函数中存在拼写错误。尝试将static DefinedInstances()更改为static DefinedInstancesBase(),因为目前它只是指定为私有静态函数。
  2. 第二个也是更重要的问题是理解调用各种构造函数的顺序。发生的事情是基础抽象类上的静态构造函数由{的成员初始化程序中的实例化触发)触发派生类中的{1}}字段。因此,当First类的First构造函数被调用时,static仍为null(因此DefinedInstancesBase方法)。
  3. 请参阅以下代码(稍加修改以更好地说明问题)和输出:

    FindAll()