CLR Via C# 第四章 类型基础——读书笔记

来源:互联网 发布:成都数据恢复公司 编辑:程序博客网 时间:2024/05/21 02:35

1.类型转换


在以下示例代码中,第一部分能通过编译,因为方法PromoteEmoloyee期待一个Object,而Manage正是Object一个派生类,所以能进入该方法,
进入方法后,o是Manager对象的引用,由于对o向Employee转型,CLR核实对象o引用的是一个Emoloyee或是其派生类对象,核实成功,CLR执行转型。

而第二部分,同理,DateTime能够进入方法,但是,CLR检查类型转换时发现o的引用既不是Employee,也不是其派生类型,此时CLR会禁止转型,抛出System.InvalidCastException异常

这个示例体现了CLR的类型安全,

特别地,此程序可以在方法的参数中将类型改为Employee(基类),从而使得程序在编译时就发现错误。

public static void Main2() {      // Construct a Manager object and pass it to PromoteEmployee.      // A Manager IS-A Object: PromoteEmployee runs OK.      Manager m = new Manager();//第一部分      PromoteEmployee(m);      // Construct a DateTime object and pass it to PromoteEmployee.      // A DateTime is NOT derived from Employee. PromoteEmployee       // throws a System.InvalidCastException exception.       DateTime newYears = new DateTime(2007, 1, 1);//第二部分      PromoteEmployee(newYears);   }

 public static void PromoteEmployee(Object o) {      // At this point, the compiler doesn't know exactly what      // type of object o refers to. So the compiler allows the       // code to compile. However, at run time, the CLR does know       // what type o refers to (each time the cast is performed) and      // it checks whether the object抯 type is Employee or any type      // that is derived from Employee.      Employee e = (Employee) o;   }

2.借助C#得 is,as 操作符来转型

以下示例程序中,这是常用的写法,
但是,
if (o is Employee) {         Employee e = (Employee)o;         // Use e within the remainder of the 'if' statement.       }
在这种写法中,is操作符核实o是否兼容于Employee类型,如果是,则进入if语句内,CLR再次核实o是否引用一个Employee,
可见对性能造成一定影响。

所以提供as操作符,此操作符核实o是否兼容于Employee类型,若是则返回同一对象的非null引用,否则返回null
Employee e = o as Employee;      if (e != null) {         // Use e within the 'if' statement.      }

3.类型,对象,线程栈和托管堆在运行时的相互关系

所有堆上的对象都包含两个额外成员:类型对象指针和同步块索引
类型对象:方法初始化时CLR利用元数据提取这些类型相关的信息,创建一个数据结构描述类型本身,称作类型对象,其后定义的对象,对象的类型对象指针指向相应的类型对象。


a.调用Employee的静态方法Lookup,CLR定位于定义静态方法的类型对应的类型对象,JIT编译器在类型对象的方法表中查找被调用方法对应的记录项,进行JIT编译(如需要),再调用JIT编译好的代码。




b.调用非虚实例方法,JIT编译器找到调用的那个变量(e)的类型(Employee),如果该类型中没那个方法,则回溯类层次结构(直到object)查找方法。




c.调用虚实例方法(多态),JIT编译器找到发出调用的实际对象,发现是一个Manage对象(上一步初始化了一个Manage对象并将地址保存到e),跟随其中类型对象指针找到该实际类型,在类型对象方法表中找到该方法的记录项,进行JIT编译(如需要)。



注:类型对象本质也是对象,CLR在创建类型对象时,会使用System.Type类创建一些特殊类型对象,Employee,Manager类型对象都是Type类型的“实例”
特别地,而Type类型对象本身也是类型,内部的类型对象指针则指向本身。
System.object 中的GetType方法中获得的就是返回对象的类型对象的指针


0 0