下面是初始化靜態只讀字段的兩種不同方法。這兩種方法有什麼區別?如果是,什麼時候應該比另一個更受歡迎?靜態只讀字段初始值設定項與靜態構造函數初始化
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. 靜態初始化數組?
- 6. 靜態字段/屬性初始化
- 7. 靜態字段無法初始化
- 8. Java靜態字段初始化
- 9. 當靜態字段初始化發生?
- 10. 類型初始值設定項(靜態構造函數)異常處理
- 11. 靜態初始化與動態初始化
- 12. 在實例的構造函數中初始化靜態成員
- 13. 使用靜態構造函數初始化一個類?
- 14. 是需要初始化靜態變量的構造函數嗎?
- 15. 枚舉構造函數靜態初始化程序
- 16. 由於靜態初始化而被調用的構造函數
- 17. 使用靜態初始化函數
- 18. 訪問Haxe靜態字段的靜態初始化的非靜態數據
- 19. 靜態HashMap的初始化
- 20. 靜態變量初始化
- 21. 靜態初始化混淆
- 22. 靜態變量初始化
- 23. 靜態變量初始化
- 24. 初始化靜態向量
- 25. 靜態ImmutableArray未初始化
- 26. Spring的靜態初始化
- 27. 靜態對象初始化
- 28. 靜態屬性初始化
- 29. 靜態初始化C++
- 30. 初始化靜態變量