nev*_*gqs 11 c# static synchronous
鉴于:
public class MyClass
{
private static readonly Dictionary<string,int> mydict = CreateDictionary();
private static Dictionary<string,int> CreateDictionary() { ... }
}
Run Code Online (Sandbox Code Playgroud)
这是同步完成的吗?(即可以两次快速实例化MyClass原因CreateDictionary()被调用两次?
xan*_*tos 10
是的,这是线程安全的.C#静态构造函数线程是否安全?
在创建类的任何实例或访问任何静态成员之前,保证每个应用程序域只运行一次静态构造函数.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
Run Code Online (Sandbox Code Playgroud)
其中.cctor是静态构造函数的特殊名称.呼叫CreateDictionary和分配mydict非常明显.
接受的答案是正确的; 初始化将发生零次或一次但不会发生两次.但我想补充一点.在您的示例中,CLR和C#语言保留了比您预期更早地初始化字段的权限.如果你写:
public class MyClass
{
private static readonly Dictionary<string,int> mydict = CreateDictionary();
static MyClass() {}
Run Code Online (Sandbox Code Playgroud)
然后CLR和C#保证在调用第一个静态方法MyClass或MyClass创建第一个实例时初始化该字段.如果省略静态构造函数,则允许CLR和C#(但不是必需)在这些事件之前的任何时间初始化字段.特别是,假设您有一个M调用静态方法的方法MyClass.CLR可能决定运行MyClass.mydict 何时Mjitted的静态初始化程序,而不是在M实际调用静态方法时.这可以在一些罕见的情况下导致令人惊讶的结果.
对beforefieldinit优化进行Web搜索以获取更多详细信息.Jon Skeet有一篇很好的文章.