1 引言
今天Artech兄在
![](/icons/26433smhl.gif)
有关Type Initializer和 BeforeFieldInit
![](/icons/26433de.gif)
问题
![](/icons/26433dou.gif)
看看大家能否给出正确
![](/icons/26433de.gif)
解释
![](/icons/26433smhr.gif)
![](/icons/26433yi.gif)
文中让我们认识了
![](/icons/26433yi.gif)
个有关类型构造器
![](/icons/26433diaoyong.gif)
执行
![](/icons/26433de.gif)
有趣举例
![](/icons/26433dou.gif)
其中也相应提出了
![](/icons/26433yi.gif)
些有关beforefieldinit对于类型构造器
![](/icons/26433diaoyong.gif)
时机
![](/icons/26433de.gif)
探讨
![](/icons/26433dou.gif)
对于我们很好
![](/icons/26433de.gif)
理解类型构造器给出了
![](/icons/26433yi.gif)
个很好
![](/icons/26433de.gif)
应用实战体验
作为补充
![](/icons/26433dou.gif)
本文希望从基础开始再层层深入
![](/icons/26433dou.gif)
把
![](/icons/26433smhl.gif)
有关Type Initializer和 BeforeFieldInit
![](/icons/26433de.gif)
问题
![](/icons/26433dou.gif)
看看大家能否给出正确
![](/icons/26433de.gif)
解释
![](/icons/26433smhr.gif)
![](/icons/26433yi.gif)
文中没有解释
![](/icons/26433de.gif)
概念和原理
![](/icons/26433dou.gif)
进行必要
![](/icons/26433de.gif)
补充
![](/icons/26433dou.gif)
例如更全面
![](/icons/26433de.gif)
认识类型构造器
![](/icons/26433dou.gif)
认识BeforeFieldInit
![](/icons/26433dou2.gif)
并在此基础上
![](/icons/26433dou.gif)
探讨
![](/icons/26433yi.gif)
点有关类型构造器
![](/icons/26433de.gif)
实战应用
![](/icons/26433dou.gif)
同时期望能够回答其中举例运行
![](/icons/26433de.gif)
结果
废话少说
![](/icons/26433dou.gif)
我们开始
2 认识对象构造器和类型构造器
在.NET中
![](/icons/26433dou.gif)
![](/icons/26433yi.gif)
个类
![](/icons/26433de.gif)
![](/icons/26433chushi.gif)
化过程是在构造器中进行
![](/icons/26433de.gif)
![](/icons/26433dou2.gif)
并且根据构造成员
![](/icons/26433de.gif)
类型
![](/icons/26433dou.gif)
分为类型构造器(.cctor)和对象构造器(.ctor)
![](/icons/26433dou.gif)
其中.cctor和.ctor为 2者在IL代码中
![](/icons/26433de.gif)
指令表示
![](/icons/26433dou2.gif)
.cctor不能被直接
![](/icons/26433diaoyong.gif)
![](/icons/26433dou.gif)
其
![](/icons/26433diaoyong.gif)
规则正是本文欲加阐述
![](/icons/26433de.gif)
重点
![](/icons/26433dou.gif)
详见后文
![](/icons/26433de.gif)
分析;而.ctor会在类型例子化时被自动
![](/icons/26433diaoyong.gif)
基于对类型构造器
![](/icons/26433de.gif)
探讨
![](/icons/26433dou.gif)
我们有必要首先实现
![](/icons/26433yi.gif)
个简单
![](/icons/26433de.gif)
类定义
![](/icons/26433dou.gif)
其中包括普通
![](/icons/26433de.gif)
构造器和静态构造器
![](/icons/26433dou.gif)
例如
// Release : code01, 2008/11/02 // Author : Anytao, http://www.anytao.com public
![](/icons/26433class.gif)
User {
![](/icons/26433static.gif)
User
![](/icons/26433kh.gif)
{ message = "Initialize in
![](/icons/26433static.gif)
constructor."; } public User
![](/icons/26433kh.gif)
{ message = "Initialize in normal construcotr."; } public User(
![](/icons/26433string.gif)
name,
![](/icons/26433int.gif)
age) { Name = name; Age = age; } public
![](/icons/26433string.gif)
Name { get;
![](/icons/26433set.gif)
; } public
![](/icons/26433int.gif)
Age { get;
![](/icons/26433set.gif)
; } public
![](/icons/26433string.gif)
message = "Initialize when
![](/icons/26433define.gif)
d.";我们将上述代码使用ILDasm.exe工具反编译为IL代码
![](/icons/26433dou.gif)
可以很方便
![](/icons/26433de.gif)
找到相应
![](/icons/26433de.gif)
类型构造器和对象构造器
![](/icons/26433de.gif)
影子
![](/icons/26433dou.gif)
如图
然后
![](/icons/26433dou.gif)
我们简单
![](/icons/26433de.gif)
来了解
![](/icons/26433yi.gif)
下对象构造器和类型构造器
![](/icons/26433de.gif)
概念
对象构造器(.ctor)
在生成
![](/icons/26433de.gif)
IL代码中将可以看到对应
![](/icons/26433de.gif)
ctor
![](/icons/26433dou.gif)
类型例子化时会执行对应
![](/icons/26433de.gif)
构造器进行类型
![](/icons/26433chushi.gif)
化
![](/icons/26433de.gif)
操作
有关例子化
![](/icons/26433de.gif)
过程
![](/icons/26433dou.gif)
设计到比较复杂
![](/icons/26433de.gif)
执行顺序
![](/icons/26433dou.gif)
按照类型基础层次进行
![](/icons/26433chushi.gif)
化
![](/icons/26433de.gif)
过程可以参阅
![](/icons/26433smhl.gif)
你必须知道
![](/icons/26433de.gif)
.NET
![](/icons/26433smhr.gif)
7.8节 “动静的间:静态和非静态”
![](/icons/26433yi.gif)
文中有详细
![](/icons/26433de.gif)
介绍和分析
![](/icons/26433dou.gif)
本文中将不做过多探讨
本文
![](/icons/26433de.gif)
重点以考察类型构造器为主
![](/icons/26433dou.gif)
所以在此不进行过多探讨
类型构造器(.cctor)
用于执行对静态成员
![](/icons/26433de.gif)
![](/icons/26433chushi.gif)
化
![](/icons/26433dou.gif)
在.NET中
![](/icons/26433dou.gif)
类型在两种情况下会发生对.cctor
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
:
为静态成员指定
![](/icons/26433chushi.gif)
值
![](/icons/26433dou.gif)
例如上例中只有静态成员
![](/icons/26433chushi.gif)
化
![](/icons/26433dou.gif)
而没有静态构造
![](/icons/26433hanshu.gif)
时
![](/icons/26433dou.gif)
.cctor
![](/icons/26433de.gif)
IL代码实现为:
.method private hidebysig specialname rtspecialname
![](/icons/26433static.gif)
void .cctor
![](/icons/26433kh.gif)
cil managed{ // Code size 11 (0xb) .maxstack 8 IL_0000: ldstr "Initialize when
![](/icons/26433define.gif)
d." IL_0005: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message IL_000a: ret} // end of method User::.cctor实现显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
例如上例中有静态构造
![](/icons/26433hanshu.gif)
存在时
![](/icons/26433dou.gif)
将首先执行静态成员
![](/icons/26433de.gif)
![](/icons/26433chushi.gif)
化过程
![](/icons/26433dou.gif)
再执行静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433chushi.gif)
化过程
![](/icons/26433dou.gif)
.cctor
![](/icons/26433de.gif)
IL代码实现为:
.method private hidebysig specialname rtspecialname
![](/icons/26433static.gif)
void .cctor
![](/icons/26433kh.gif)
cil managed{ // Code size 23 (0x17) .maxstack 8 IL_0000: ldstr "Initialize when
![](/icons/26433define.gif)
d." IL_0005: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message IL_000a: nop IL_000b: ldstr "Initialize in
![](/icons/26433static.gif)
constructor." IL_0010: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message IL_0015: nop IL_0016: ret} // end of method User::.cctor同时
![](/icons/26433dou.gif)
我们必须明确
![](/icons/26433yi.gif)
些静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433de.gif)
基本规则
![](/icons/26433dou.gif)
包括:
必须为静态无参构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
并且
![](/icons/26433yi.gif)
个类只能有
![](/icons/26433yi.gif)
个
只能对静态成员进行
![](/icons/26433chushi.gif)
化
静态无参构造
![](/icons/26433hanshu.gif)
可以和非静态无参构造
![](/icons/26433hanshu.gif)
共存
![](/icons/26433dou.gif)
区别在于 2者
![](/icons/26433de.gif)
执行时间
![](/icons/26433dou.gif)
详见
![](/icons/26433smhl.gif)
你必须知道
![](/icons/26433de.gif)
.NET
![](/icons/26433smhr.gif)
7.8节 “动静的间:静态和非静态”
![](/icons/26433de.gif)
论述
![](/icons/26433dou.gif)
其他更多
![](/icons/26433de.gif)
区别和差异也详见本节
![](/icons/26433de.gif)
描述
3 深入执行过程
![](/icons/26433yinwei.gif)
类型构造器本身
![](/icons/26433de.gif)
特点
![](/icons/26433dou.gif)
在
![](/icons/26433yi.gif)
定程度上决定了.cctor
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
时机并非是
![](/icons/26433yi.gif)
个确定
![](/icons/26433de.gif)
概念
![](/icons/26433dou2.gif)
![](/icons/26433yinwei.gif)
类型构造器都是private
![](/icons/26433de.gif)
![](/icons/26433dou.gif)
用户不能显式
![](/icons/26433diaoyong.gif)
类型构造器
![](/icons/26433dou2.gif)
所以有关类型构造器
![](/icons/26433de.gif)
执行时机问题在.NET中主要包括两种方案:
precise方式
beforefieldinit方式
2者
![](/icons/26433de.gif)
执行差别主要体现在是否为类型实现了显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
如果实现了显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
则按照precise方式执行;如果没有实现显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
则按照beforefieldinit方式执行
为了说清楚类型构造器
![](/icons/26433de.gif)
执行情况
![](/icons/26433dou.gif)
我们首先在概念上必须明确
![](/icons/26433yi.gif)
个前提
![](/icons/26433dou.gif)
那就是precise
![](/icons/26433de.gif)
语义明确了.cctor
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
和
![](/icons/26433diaoyong.gif)
存取静态成员
![](/icons/26433de.gif)
时机存在精确
![](/icons/26433de.gif)
关系
![](/icons/26433dou.gif)
所以换句话说
![](/icons/26433dou.gif)
类型构造器
![](/icons/26433de.gif)
执行时机在语义上决定于是否显式
![](/icons/26433de.gif)
声明了静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433dou.gif)
以及存取静态成员
![](/icons/26433de.gif)
时机
![](/icons/26433dou.gif)
这两个原因
我们还是从User类
![](/icons/26433de.gif)
实现说起
![](/icons/26433dou.gif)
![](/icons/26433yi.gif)
![](/icons/26433yi.gif)
过招分析这两种方式
![](/icons/26433de.gif)
执行过程
3.1 precise方式
首先实现显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
方案
![](/icons/26433dou.gif)
为:
// Release : code02, 2008/11/02 // Author : Anytao, http://www.anytao.com public
![](/icons/26433class.gif)
User { //Explicit Constructor
![](/icons/26433static.gif)
User
![](/icons/26433kh.gif)
{ message = "Initialize in
![](/icons/26433static.gif)
constructor."; } public
![](/icons/26433string.gif)
message = "Initialize when
![](/icons/26433define.gif)
d."; }对应
![](/icons/26433de.gif)
IL代码为:
.
![](/icons/26433class.gif)
public auto ansi User extends [mscorlib]
![](/icons/26433System.gif)
.Object{ .method private hidebysig specialname rtspecialname
![](/icons/26433static.gif)
void .cctor
![](/icons/26433kh.gif)
cil managed { .maxstack 8 L_0000: ldstr "Initialize when
![](/icons/26433define.gif)
d." L_0005: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message L_000a: nop L_000b: ldstr "Initialize in
![](/icons/26433static.gif)
constructor." L_0010: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message L_0015: nop L_0016: ret } .method public hidebysig specialname rtspecialname instance void .ctor
![](/icons/26433kh.gif)
cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]
![](/icons/26433System.gif)
.Object::.ctor
![](/icons/26433kh.gif)
L_0006: ret } .field public
![](/icons/26433string.gif)
message}为了进行对比分析
![](/icons/26433dou.gif)
我们需要首先分析beforefieldinit方式
![](/icons/26433de.gif)
执行情况
![](/icons/26433dou.gif)
所以接着继续
![](/icons/26433dou2.gif)
![](/icons/26433dou2.gif)
3.2 beforefieldinit方式
为User类型
![](/icons/26433dou.gif)
不实现显式
![](/icons/26433de.gif)
静态构造
![](/icons/26433hanshu.gif)
方案
![](/icons/26433dou.gif)
为:
// Release : code03, 2008/11/02 // Author : Anytao, http://www.anytao.com public
![](/icons/26433class.gif)
User { //Implicit Constructor public
![](/icons/26433string.gif)
message = "Initialize when
![](/icons/26433define.gif)
d."; }对应
![](/icons/26433de.gif)
IL代码为:
.
![](/icons/26433class.gif)
public auto ansi beforefieldinit User extends [mscorlib]
![](/icons/26433System.gif)
.Object{ .method private hidebysig specialname rtspecialname
![](/icons/26433static.gif)
void .cctor
![](/icons/26433kh.gif)
cil managed { .maxstack 8 L_0000: ldstr "Initialize when
![](/icons/26433define.gif)
d." L_0005: stsfld
![](/icons/26433string.gif)
Anytao.Write.TypeInit.User::message L_000a: ret } .method public hidebysig specialname rtspecialname instance void .ctor
![](/icons/26433kh.gif)
cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]
![](/icons/26433System.gif)
.Object::.ctor
![](/icons/26433kh.gif)
L_0006: ret } .field public
![](/icons/26433string.gif)
message}3.3 分析差别
从IL代码
![](/icons/26433de.gif)
执行过程而言
![](/icons/26433dou.gif)
我们首先可以了解
![](/icons/26433de.gif)
是在显式和隐式实现类型构造
![](/icons/26433hanshu.gif)
![](/icons/26433de.gif)
内部
![](/icons/26433dou.gif)
除了添加新
![](/icons/26433de.gif)
![](/icons/26433chushi.gif)
化操作的外
![](/icons/26433dou.gif)
2者
![](/icons/26433de.gif)
实现是基本相同
![](/icons/26433de.gif)
![](/icons/26433dou2.gif)
所以要找出两种方式
![](/icons/26433de.gif)
差别
![](/icons/26433dou.gif)
我们最终将着眼点锁定在 2者元数据
![](/icons/26433de.gif)
声明上
![](/icons/26433dou.gif)
隐式方式多了
![](/icons/26433yi.gif)
个称为beforefieldinit标记
![](/icons/26433de.gif)
指令
那么
![](/icons/26433dou.gif)
beforefieldinit究竟表示什么样
![](/icons/26433de.gif)
语义呢?Scott Allen对此进行了详细
![](/icons/26433de.gif)
解释:beforefieldinit为CLR提供了在任何时候执行.cctor
![](/icons/26433de.gif)
授权
![](/icons/26433dou.gif)
只要该思路方法在第
![](/icons/26433yi.gif)
次访问类型
![](/icons/26433de.gif)
静态字段的前执行即可
所以
![](/icons/26433dou.gif)
如果对precise方式和beforefieldinit方式进行比较时
![](/icons/26433dou.gif)
2者
![](/icons/26433de.gif)
差别就在于是否在元数据声明时标记了beforefieldinit指令
![](/icons/26433dou2.gif)
precise方式下
![](/icons/26433dou.gif)
CLR必须在第
![](/icons/26433yi.gif)
次访问该类型
![](/icons/26433de.gif)
静态成员或者例子成员的前执行类型构造器
![](/icons/26433dou.gif)
也就是说必须刚好在存取静态成员或者创建例子成员的前完成类型构造器
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
;beforefieldinit方式下
![](/icons/26433dou.gif)
CLR可以在任何时候执行类型构造器
![](/icons/26433dou.gif)
![](/icons/26433yi.gif)
定程度上实现了对执行性能
![](/icons/26433de.gif)
优化
![](/icons/26433dou.gif)
因此较precise方式更加高效
值得注意
![](/icons/26433de.gif)
是
![](/icons/26433dou.gif)
当有多个beforefieldinit构造器存在时
![](/icons/26433dou.gif)
CLR无法保证这多个构造器的间
![](/icons/26433de.gif)
执行顺序
![](/icons/26433dou.gif)
因此我们在实际
![](/icons/26433de.gif)
编码时应该尽量避免这种情况
![](/icons/26433de.gif)
发生
4 回归问题
![](/icons/26433dou.gif)
必要
![](/icons/26433de.gif)
小结
本文源于Artech兄
![](/icons/26433de.gif)
![](/icons/26433yi.gif)
个问题
![](/icons/26433dou.gif)
希望通过上文
![](/icons/26433de.gif)
分析可以给出
![](/icons/26433yi.gif)
点值得参考
![](/icons/26433de.gif)
背景
![](/icons/26433dou2.gif)
现在就有关Type Initializer和 BeforeFieldInit
![](/icons/26433de.gif)
问题
![](/icons/26433dou.gif)
看看大家能否给出正确
![](/icons/26433de.gif)
解释
![](/icons/26433yi.gif)
文中
![](/icons/26433de.gif)
几个举例进行
![](/icons/26433yi.gif)
些继续
![](/icons/26433de.gif)
分析:
在蒋兄
![](/icons/26433de.gif)
开始
![](/icons/26433de.gif)
举例实现中
![](/icons/26433dou.gif)
可以很容易
![](/icons/26433de.gif)
来确定对于显式实现了静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433de.gif)
情况
![](/icons/26433dou.gif)
类型构造器
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
在刚好引用静态成员的前发生
![](/icons/26433dou.gif)
所以不管是否在Main中声明
![](/icons/26433string.gif)
field = Foo.Field;执行
![](/icons/26433de.gif)
结果不受影响
而在没有显式实现静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433de.gif)
情况下
![](/icons/26433dou.gif)
beforefieldinit优化了类型构造器
![](/icons/26433de.gif)
执行不在确定
![](/icons/26433de.gif)
时间执行
![](/icons/26433dou.gif)
只要实在静态成员引用或者类型例子发生的前即可
![](/icons/26433dou.gif)
所以在Debug环境下
![](/icons/26433diaoyong.gif)
![](/icons/26433de.gif)
时机变得不按常理
![](/icons/26433dou2.gif)
然而在Release优化模式下
![](/icons/26433dou.gif)
beforefieldinit
![](/icons/26433de.gif)
执行顺序并不受
![](/icons/26433string.gif)
field = Foo.Field;
![](/icons/26433de.gif)
影响
![](/icons/26433dou.gif)
完全符合beforefieldinit优化执行
![](/icons/26433de.gif)
语义定义
有关最后
![](/icons/26433yi.gif)
个静态成员继承情况
![](/icons/26433de.gif)
结果
![](/icons/26433dou.gif)
正像本文开始描述
![](/icons/26433de.gif)
逻辑
![](/icons/26433yi.gif)
样
![](/icons/26433dou.gif)
类型构造器是在静态成员被
![](/icons/26433diaoyong.gif)
或者创建例子时发生
![](/icons/26433dou.gif)
所以举例
![](/icons/26433de.gif)
结果是完全遵守规范标准
![](/icons/26433de.gif)
![](/icons/26433dou2.gif)
不过
![](/icons/26433dou.gif)
我并不建议子类最好不要
![](/icons/26433diaoyong.gif)
父类静态成员
![](/icons/26433dou.gif)
原因是作为继承机制而言
![](/icons/26433dou.gif)
子承父业是继承
![](/icons/26433de.gif)
基本规范标准
![](/icons/26433dou.gif)
除了强制为private的外
![](/icons/26433dou.gif)
所有
![](/icons/26433de.gif)
成员或者思路方法都应在子类中可见
![](/icons/26433dou2.gif)
而对于存在
![](/icons/26433de.gif)
潜在问题
![](/icons/26433dou.gif)
更好
![](/icons/26433de.gif)
以规范标准来约束可能会更好
![](/icons/26433dou2.gif)
其中
![](/icons/26433dou.gif)
静态思路方法
![](/icons/26433yi.gif)
定程度上是
![](/icons/26433yi.gif)
种结构化
![](/icons/26433de.gif)
实现机制
![](/icons/26433dou.gif)
在面向对象
![](/icons/26433de.gif)
继承关系中
![](/icons/26433dou.gif)
本质上就存在
![](/icons/26433yi.gif)
定
![](/icons/26433de.gif)
不足
在c#规范标准中
![](/icons/26433dou.gif)
有关beforefieldinit
![](/icons/26433de.gif)
控制已经引起很多
![](/icons/26433de.gif)
关注和非议
![](/icons/26433dou.gif)
![](/icons/26433yi.gif)
方面beforefieldinit方式可以有效
![](/icons/26433de.gif)
优化
![](/icons/26433diaoyong.gif)
性能
![](/icons/26433dou.gif)
但是以显式和或者隐式实现静态构造
![](/icons/26433hanshu.gif)
![](/icons/26433de.gif)
方式不能更有直观
![](/icons/26433de.gif)
让
![](/icons/26433chengxu.gif)
开发者来控制
![](/icons/26433dou.gif)
因此在以后版本
![](/icons/26433de.gif)
c#中
![](/icons/26433dou.gif)
能实现基于特性
![](/icons/26433de.gif)
声明方式来控制
![](/icons/26433dou.gif)
是值得期待
![](/icons/26433de.gif)
另
![](/icons/26433yi.gif)
方面
![](/icons/26433dou.gif)
在有两个类型
![](/icons/26433de.gif)
类型构造器相互引用
![](/icons/26433de.gif)
情况下
![](/icons/26433dou.gif)
CLR无法保证类型构造器
![](/icons/26433de.gif)
![](/icons/26433diaoyong.gif)
顺序
![](/icons/26433dou.gif)
对
![](/icons/26433chengxu.gif)
开发者而言
![](/icons/26433dou.gif)
我同样强调了对于类型构造器而言
![](/icons/26433dou.gif)
我们应该尽量避免要求顺序相关
![](/icons/26433de.gif)
业务逻辑
![](/icons/26433dou.gif)
![](/icons/26433yinwei.gif)
很多时候执行
![](/icons/26433de.gif)
顺序并非声明
![](/icons/26433de.gif)
顺序
![](/icons/26433dou.gif)
这是值得关注
![](/icons/26433de.gif)