下面是初始化静态只读字段的两种不同方法。这两种方法有什么区别?如果是,什么时候应该比另一个更受欢迎?静态只读字段初始值设定项与静态构造函数初始化
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. C++静态初始化VS __attribute __((构造))
- 5. 静态只读变量初始化
- 6. 静态初始化
- 7. 在构造函数中初始化静态函数指针
- 8. 静态初始化数组?
- 9. 静态字段无法初始化
- 10. 通用静态字段初始化
- 11. 静态字段/属性初始化
- 12. java球衣静态字段初始化
- 13. 静态字段初始化使用AST
- 14. Java静态字段初始化
- 15. 当静态字段初始化发生?
- 16. 静态初始化C++,未设置值
- 17. 静态或公共构造函数的数据初始化
- 18. 类型初始值设定项(静态构造函数)异常处理
- 19. 静态初始化与动态初始化
- 20. Python中是否存在静态构造函数或静态初始化器?
- 21. 在静态构造函数中初始化容器
- 22. 是需要初始化静态变量的构造函数吗?
- 23. 使用静态构造函数初始化一个类?
- 24. 在实例的构造函数中初始化静态成员
- 25. 由于静态初始化而被调用的构造函数
- 26. 做默认构造函数初始化的静态变量?
- 27. 在构造函数中初始化静态泛型列表
- 28. 构造函数java中的静态变量初始化java
- 29. 枚举构造函数静态初始化程序
- 30. 使用静态初始化函数