2010-05-03 4 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 메커니즘이 가능합니다.