CLR是围绕类型工作的.所以在此有必要介绍一下CLR支持的两种类型值类型和引用类型.值类型的基类是System.ValueType,引用类型的基类是System.Object.  Framework 类库提供的类型中,大部份是引用类型.而程序的开发过程中经常用的是值类型.值类型可以提高运用程序的性能.如果一个运用程序都使用引用类型.那么这个运程的性能应该是很糟糕.运用程序执行时,值类型在线程堆栈上分配,而引用类型在托管堆中分配.下面举个例子说明值类型和引用类型在运用程序执行过程中的区别.

Code

     以上是一个比较简单的例子,是关于教师和校长的一个应用程序,教师类型中,有获取教龄,工作内容,查找等操作。运用程序执行时。运用程序的进程首先加载CLR,初始化托管堆(Mangaged Heap)和线程堆栈(Stread Stack). JIT 编译器将应用程序集的中间语言代码(IL)转换成本地的CPU指令(Native code),与此同时,CLR确保应用程序所有类型的程序集都被加载到应用程序域中,接着CLR查找程序集的元数据,提取信息为每个类型分配数据结构。Teacher和President类型是引用类型,数据结构在托管堆(Managed Heap)中分配,如下图:

     

解释一下这两个类型,引用类型的每一个对象在托管堆上分配都有两个额外的对象:类型对象指针(Type object pointer)和同步块索引(Sync block index),这两个成员是CLR用来管理对象。静态字段(Static fields)充许类型内定义的静态数据。虚线下面表示,每个类型对象都包含一张方法表,这张方法表是用来保存每个方法的入口点。如当某个对象调用该对象的某个方法时。就是通过这张方法表来查找对应的方法。从上图可以看出President类型对象方法表只有一个方法。而Teacher类型对象的方法表有三个方法。

     CLR确定Main()方法所需要的Teacher和President类型对象创建和Main()方法被编译成本地的CPU指令后。应用程序的主线程,开始执行main()方法。Main()方法执行时,CLR自动初始化两个本地变量,引用类型初始化为null,值类型初始化为0(分配在线程堆栈上),也就是执行代码的21和22行。如下图

当代码执行到23行时,构建President对象,这时托管堆中,新创建了一个President对象指向President 类型对象( 注意:President对象和President类型对象是不一样的).如下图:

 

如上图新创建的President对象和其它所有的对象一样也包含类型对象指针(Type object pointer)和同步块索引(Sync block index),与类型对象有所不同的是这里包含实例化字段来存储任何基类的实例.当president对象创建时,CLR自动初始化president对象的类型对象指针(Type object pointer)指向对应的President类型对象.同时CLR也初始化了同步块索引(Sync block index).CLR将new操作(实例化President对象)返回的内存地址保存在变量t中(在线程堆栈上).

     当执行24行代码,调用Teacher对象的Lookup静态方法,CLR先在Teacher类型对象的方法表上查找Lookup的方法入口点,接着执行Lookup方法。 假设通过Lookup()查找数据库,得到的结果是Jon是学校的校长(President).因此,间接的Lookup方法在托管堆上创建了一个新的President对象,初始化了Jon,同时将返回的内存地址保存在变量t中。注意:这时的返回的内存地址复盖掉上行代码返回的内存地址。也就是说,变量t不再指向第一个president对象,实际上,也没有其它就量去引用第一个President对象,CLR垃圾回收器会首先释放President对象的内存空间。如下图

 

当执行25行代码,CLR在Teacher类型对象的方法表中查找到GetYearsTeached方法入口并执行。这里要说明一下CLR查找的顺序是从子类到基类,这里是从President类型对象方法表开始查找,没找到,再从基类Teacher类型对象方法表中查找到。假设GetYearsTeached方法返回Jon的教龄是10,并将返回的结果保存在线程堆栈上的变量year中,如下图

 

当执行26代码,调用Teacher对象的虚方法GetProcessReport,CLR查找并检查该方法实现类型,这个例子是President类型对象.即通过President类型对象的方法表查找并执行GetProcessRepor方法.下图标出了这三个方法的本地CPU代码在实现类中位置

注意:如果Teacher对象的Lookup方法查找出来Jon只是一个教师而不是校长,那么,构建的t实例是teacher对象.则执行t.GetProcessReport是调用Teacher对象的GetProcessReport方法.从以上这些图可以看出Teacher和President类型对象都包含类型对象指针,那么他们的类型对象指针会指向哪里?当CLR开始在进程中执行时,立即创建一个特殊的System.Type类型对象.President和Teacher类型对象都是System.Type类型对像的实例.所以President和Teacher类型对象指针指向System.Type 类型对象.另外再说一下System.Type类型对象是它本身的一个实例.所以System.Type类型对象指针指向它本身.如下图: