第四章:类型基础

  我们知道,CLR要求每个类型最终都从System.Object类型派生。而Object类提供了几个实例方法:Equals(),GetHashCode(),ToString(),GetType().

     当我们new一个对象时,CLR所做的工作如下:(1)计算类型及其所有基类型中定义的所有实例字段需要的字节数,其中包括两个额外的成员:“类型对象指针”和“同步索引块”;

(2)从托管堆上分配指定类型所要求的字节数,从而分配对象的内存,分配的所有字节都设为0;(3)初始化对象的“类型对象指针”和“同步索引块”(4)调用类型的实例构造器,构

造器负责实例化类型中的字段,并最终调用System.Object的构造器,然后返回。注意:分配的内存最终由CLR的GC收集。

类型转换

  C#不要求任何特殊语法即可将一个对象转化为它的任何基类型,因为向基类型的转换被认为是一种安全的隐式转换。然而,将对象转化为它的某个派生类型时,C#要求开发人员

只能进行显示转换,因为这样的转换可能在运行时失败。

  比如:class Employee{}  Object obj = new Employee(); Employee e = (Employee)obj;

运行时的相互关系

  先看下面这个例子:

internal class Employee{public Int32 GetYearsEmployed(){} public virtual String GetProgressReport(){} public static Employee Lookup(String name)}

internal sealed class Manager:Employee{publivc override String GetProgressReport(){}}

我们定义了一个Employye类和一个继承于Employee的Manager类,然后有这样一个方法:void M3(){Employee e;Int32 year;e = new Manager();e =

Employee.Lookup("joe");// 其中此方法内部范围的是一个Manager对象 year= e.GetYearsEmployed();e.GetProgressReport();} 当JIT编译器将M3的代码转换成本地CPU

指令时,CLR做了一系列动作,这里阐述主要的工作:首先加载所在的进程,并初始化它,比如分配1MB大小的线程栈,查找代码中内部引用的类型,并会MSCorLib.dll中定义的

System.Type类型创建一个特殊的类型对象。Employee和Manager类型对象都是该类型的实例,由于System.Type类型对象本身也是一个对象,它内部的”类型对象指针“指向它本

身,而Manager类型对象指针和Employee类型对象指针分别指向Type类型对象。但我们调用一个非虚实例方法(GetYearsEmployeed)时,JIT编译器会找到与”发出调用的那个

变量e的类型Employee对应的类型对象(Empoyee类型对象),而GetYearsEmployeed的方法记录项就被定义在Employee类型对象的方法表中,当调用Employee的虚实例方

法GetProgressReport时,JIT编译器要在方法中生成一些额外的代码:方法每次调用时,都会执行这些代码。这些代码首先检查发出调用的变量,然后根随地址来到发出调用的对

象。在本例中,变量e引用的是代表"Joe"的一个Manager对象,然后,代码检查对象内部的“类型对象指针”成员,这个成员指向实际的对象类型。然后,代码在类型对象的方法表中

查找引用了被调用方法的记录项,对方法进行JIT编译(如果有需要的话),再调用JIT编译过的代码,并返回。

 

 

posted @ 2012-12-23 17:00  Samguist  阅读(225)  评论(0编辑  收藏  举报