2010-05-03 47 views

回答

31

这两者之间有一个细微的区别,可以在IL代码中看到 - 将显式静态构造函数告诉C#编译器不要将该类型标记为beforefieldinit。例如,beforefieldinit影响何时运行类型初始值设定项,并且在编写lazy singletons in C#时很有用。

简单的区别是:

.class private auto ansi beforefieldinit A 
.class private auto ansi B 

在所有其他方面它们是相同的。从反射器输出:

A类:

.class private auto ansi beforefieldinit A 
    extends [mscorlib]System.Object 
{ 
    .method private hidebysig specialname rtspecialname static void .cctor() cil managed 
    { 
     .maxstack 8 
     L_0000: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection> WebConfigurationManager::ConnectionStrings 
     L_0005: ldstr "SomeConnection" 
     L_000a: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection>::get_Item(!0) 
     L_000f: ldfld string Connection::ConnectionString 
     L_0014: stsfld string A::connectionString 
     L_0019: ret 
    } 

    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed 
    { 
     .maxstack 8 
     L_0000: ldarg.0 
     L_0001: call instance void [mscorlib]System.Object::.ctor() 
     L_0006: ret 
    } 

    .field private static initonly string connectionString 
} 

B类:

.class private auto ansi B 
    extends [mscorlib]System.Object 
{ 
    .method private hidebysig specialname rtspecialname static void .cctor() cil managed 
    { 
     .maxstack 8 
     L_0000: nop 
     L_0001: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection> WebConfigurationManager::ConnectionStrings 
     L_0006: ldstr "SomeConnection" 
     L_000b: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection>::get_Item(!0) 
     L_0010: ldfld string Connection::ConnectionString 
     L_0015: stsfld string B::connectionString 
     L_001a: ret 
} 

    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed 
    { 
     .maxstack 8 
     L_0000: ldarg.0 
     L_0001: call instance void [mscorlib]System.Object::.ctor() 
     L_0006: ret 
    } 


    .field private static initonly string connectionString  
} 
5

它们本质上是相同的,但如果你碰巧有只读分配一个静态字段静态类型构造,只读分配第一次出现。

13

beforefieldinit属性指示初始化如何发生。

在显式静态构造函数初始化的情况下,静态成员的初始化发生在类型被访问的时刻。在A类情况下给出的例子中,初始化将仅在首先引用connectionString时发生,而在B类初始化将在第一次引用类型类B的情况下发生时,不一定要访问connectionString

只有C#(.NET 4.0)为我们提供了对如何初始化静态成员的控制权。对于VB.NET,只有非beforefieldinit方法是可能的,而使用C++/CLI只有beforefieldinit机制是可能的。