2010-05-03 83 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機制是可能的。