您的位置:首页 > 编程语言 > C#

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

2016-05-19 14:58 615 查看

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;

a3b3
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方法中获得的就是返回对象的类型对象的指针

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: