정적 읽기 전용 필드를 초기화하는 두 가지 방법은 다음과 같습니다. 두 가지 접근 방식에는 차이점이 있습니까? 그렇다면 어느 쪽을 다른 쪽보다 우선해야합니까?static readonly 필드 이니셜 라이저와 정적 생성자 초기화
30
A
답변
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 메커니즘이 가능합니다.
관련 문제
- 1. 정적 필드/속성 초기화
- 2. 일반 정적 필드 초기화
- 3. 필드 이니셜 라이저는 비 정적 필드
- 4. 개체 이니셜 라이저와 생성자의 차이점은 무엇입니까?
- 5. bcel의 정적 이니셜 라이저
- 6. Javascript 개체 - '정적 초기화'
- 7. private 생성자가 비게됩니다. private static readonly string
- 8. 정적 이니셜 라이저 함수 사용
- 9. 정적 생성자 또는 정적 초기화 프로그램이 파이썬에 있습니까?
- 10. 정적 이니셜 라이저가 AspectJ 측면에서 호출되도록 보장됩니까?
- 11. PHP의 정적 클래스 이니셜 라이저
- 12. 개체 이니셜 라이저 및 생성자
- 13. 전체 어셈블리의 정적 생성자
- 14. 생성자 이니셜 라이저에있는 멤버의 멤버 함수를 사용합니다.
- 15. 객관적인 C의 정적 이니셜 라이저
- 16. 이 생성자 이니셜 라이저 목록에서 전달
- 17. 자바 정적 인스턴스 생성자?
- 18. 장고 관리/인라인의 Readonly 필드
- 19. 정적 최종 변수 초기화
- 20. XAML의 정적 필드 액세스
- 21. VB.NET의 정적 생성자
- 22. 정적 속성 초기화
- 23. 복사 생성자 초기화 목록
- 24. 변수 초기화 및 생성자
- 25. C++ 템플릿 생성자 초기화
- 26. PHP의 정적 멤버 초기화
- 27. 종속성의 경우 정적 초기화
- 28. C 정적 변수 초기화
- 29. C# 정적 생성자 순서 지정
- 30. 정적 클래스 멤버의 초기화