如果静态只读成员调用静态方法获取值,是否同步完成?

If a static readonly member calls a static method to get a value, is it done synchronously?

鉴于:

public class MyClass
{
    private static readonly Dictionary<string,int> mydict = CreateDictionary();

    private static Dictionary<string,int> CreateDictionary() { ... }
}

这是同步完成的吗? (即 MyClass 的两个快速实例化是否会导致 CreateDictionary() 被调用两次?

是的,它是线程安全的。 Is the C# static constructor thread safe?

Static constructors are guaranteed to be run only once per application domain, before any instances of a class are created or any static members are accessed. http://msdn.microsoft.com/en-us/library/aa645612.aspx

静态字段初始化是静态构造函数的一部分。该字段是 readonly 的事实不会改变任何东西

一些要求的 IL 代码(取自 Try Roslyn http://goo.gl/ayIMG0

.method private hidebysig specialname rtspecialname static 
    void .cctor () cil managed 
{
    // Method begins at RVA 0x205f
    // Code size 11 (0xb)
    .maxstack 8

    IL_0000: call class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32> MyClass::CreateDictionary()
    IL_0005: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32> MyClass::mydict
    IL_000a: ret
} // end of method MyClass::.cctor

其中 .cctor 是静态构造函数的特殊名称。对 CreateDictionary 的调用和对 mydict 的赋值非常明显。

接受的答案是正确的;初始化将发生零次或一次,但绝不会发生两次。但我要补充一点。在您的示例中,CLR 和 C# 语言保留比您预期的 更早 初始化字段的权利。如果你写:

public class MyClass
{
    private static readonly Dictionary<string,int> mydict = CreateDictionary();
    static MyClass() {}

然后 CLR 和 C# 保证在 MyClass 上调用第一个静态方法或创建 MyClass 的第一个实例时初始化该字段。如果省略静态构造函数,则允许(但不是必需)CLR 和 C# 在这些事件 之前的任何时间初始化字段。特别是,假设您有一个方法 M,它调用 MyClass 的静态方法。 CLR 可能决定 运行 MyClass.mydict 的静态初始值设定项 M 被 jitted 时,而不是 M 实际上调用了静态方法。在极少数情况下,这可能会导致令人惊讶的结果。

在网络上搜索 beforefieldinit 优化以获取更多详细信息。 Jon Skeet 对此有一篇很好的文章。