2010-05-03 20 views

risposta

31

C'è una sottile differenza tra questi due, che può essere visto nel codice IL - mettere un costruttore esplicito statico dice al compilatore C# di non contrassegnare il tipo come beforefieldinit. Il beforefieldinit ha effetto quando viene eseguito l'inizializzatore del tipo e la conoscenza di ciò è utile quando si scrive lazy singletons in C#, ad esempio.

In breve la differenza è questa:

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

In tutti gli altri aspetti che sono gli stessi. Uscita dal riflettore:

Classe 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 
} 

Classe 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

Essi sono essenzialmente la stessa, ma se vi capita di avere sia un incarico di sola lettura a un campo statico e un tipo di costruttore statico, l'assegnazione di sola lettura si verifica per primo.

13

Il beforefieldinit attributo indica l'inizializzazione avviene.

In caso di inizializzazione di un costruttore statico esplicito, l'inizializzazione del membro statico avviene nel momento in cui si accede al tipo. Nell'esempio fornito in caso di classe A, l'inizializzazione avverrà solo quando viene fatto riferimento a connectionString, mentre in caso di inizializzazione di classe B si verificherà la prima volta che la classe di tipo B viene indirizzata, non necessariamente l'accesso a connectionString.

Solo C# (.NET 4.0) ci fornisce il controllo su come i membri statici possono essere inizializzati. Con VB.NET è possibile solo il metodo non beforefieldinit mentre con C++/CLI è possibile solo il meccanismo beforefieldinit.

Problemi correlati