C#中静态变量是如何初始化的

4

好的,我已经大幅度修改了代码以更清晰地展示实际问题。我测试过这段代码,它肯定会失败。

public class MyEnumBase
{
    private int _val;

    private static Dictionary<int, MyEnumBase> ValueMap = new Dictionary<int, MyEnumBase>();

    protected MyEnumBase()
    {
        _val = ValueMap.Count;
        ValueMap.Add(_val, this);
    }

    public static MyEnumBase ValueOf(int i)
    {
        return ValueMap[i];
    }

    public static IEnumerable<MyEnumBase> Values { get { return ValueMap.Values; } }

    public override string ToString()
    {
        return string.Format("MyEnum({0})", _val);
    }
}

public class Colors : MyEnumBase
{
    public static readonly Colors Red = new Colors();
    public static readonly Colors Green = new Colors();
    public static readonly Colors Blue = new Colors();
    public static readonly Colors Yellow = new Colors();
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("color value of 1 is " + Colors.ValueOf(2));
    }
}

以下代码失败了,因为在调用ValueOf()之前没有调用Colors构造函数。有没有一种简洁的方法来确保在调用ValueOf()之前所有的静态字段都被调用了呢?
谢谢, ~S

1
你的代码对我来说打印了3,正如预期的那样。 - BrokenGlass
是的,看起来我把我的最小情况减少得太多了。 :( - sheamus
1个回答

5
静态字段在使用前会被初始化,确切的时间取决于实现,您不应该做出任何假设。静态字段初始化的顺序如下所示:Static fields initialization
类的静态字段变量初始化器对应于按照它们在类声明中出现的文本顺序执行的一系列赋值。如果类中存在静态构造函数(第10.11节),则在执行该静态构造函数之前立即执行静态字段初始化器。否则,在第一次使用该类的静态字段之前的某个实现相关时间执行静态字段初始化器。
您发布的代码应该可以正常工作:
Child.TimesConstructed()

如果在调用这个方法之前访问了其中一个子元素(Child.C1),则不会打印出0。


这解决了我的问题。在我的实际情况中(不是人为制造的情况),我在访问子项之前调用了Child.TimesConstructed()。我曾经以为一旦调用了TimesConstructed,C1、C2、C3就会被构建。但事实并非如此。 - sheamus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接