【CLR via C#】第4章-类型基础

1.CLR最重要的特性之一就是类型安全

在运行时,CLR总是知道对象的类型是什么,调用GetType()方法即可知道对象的确切类型。这也就是为什么GetType()方法是基类Object中的非虚方法,因为如果可以重写GetType()方法,那么他返回的就不一定是当前的对象类型,违背了类型安全

2.使用 is 和 as 操作符来转型:

isas在任何情况下都不会抛出异常。

public class People{}
public class Student : People{}

在做类型判断时,我们可以使用is操作符

var p = new People();
var s = new Student();

Console.WriteLine($"{p is People}\t{p is Student}\t{s is People}\t{s is Student}"); 
//						True	       False	       True	           True

在做类型转换时,使用as操作符

// Use is
if(s is People) var pp = (People)s;------------// Use as
var pp = s as People;--------------------------

值得注意的是
①中在if中判断一次后,使用强制转换时CLR会再判断一次是否兼容,如果不兼容那么转换就会报错,所以在①中一共有两次判断。
②中有且只有CLR来判断一次,并且在不兼容的情况下,会返回null而不会抛出异常。
所以我们在转化类型时,应该使用as操作符,不仅性能高而且还安全。

3.命名空间和程序集的关系:

命名空间和程序集(实现类型的文件)不一定相关。特别是,在同一命名空间的类型可能在不同的程序集中实现。例如:在同一命名空间System.IO下的FileStream类型和FileSystemWatcher类型,其中FileStreamMSCorLib.dll程序集中实现,而FileSystemWatcherSystem.dll程序集中实现。
当然,同一个程序集也包含不同命名空间中的类型。

4.线程栈:

已加载CLR的一个Windows进程可能有多个线程,在线程创建时分配到1MB的栈,栈空间用于向方法传递实参,方法内部定义的局部变量也在栈上。

5.线程执行一个方法:

一个简单的方法包含

  • 序幕(prologue)代码,在方法开始时工作前对其进行初始化,对方法内的局部变量分配内存,CLR对其变量初始化。
  • 尾声(epilogue)代码,在方法完成工作后对其进行清理,以便返回至调用者。
6.堆上所有的对象都包含两个额外成员:
  • 类型对象指针(Type Object Pointer),任何时候在堆上新建对象,CLR都自动初始化内部的“类型对象指针”成员来应用和对象对应的类型对象。
  • 同步块索引(Sync Block Index),在调用类型的构造器(本质上是可能修改某些实例数据字段的方法)之前,CLR会先初始化同步块索引,并将对象的所有实例字段设为null或0
7.CLR创建类型对象时,必须初始化以上两个成员

我们在创建实例时

Student Hao = new Student();
Student Sin = new Student();
Teacher Jax = new Teacher();

在堆上如下
在这里插入图片描述
值得注意的是类型对象(Student、Teacher)本质上也是对象,它们的类型对象指针也必须初始化。事实上CLR开始在一个进程中运行时,会立即为MSCorLib.dll中定义的System.Type类型创建一个特殊的类型对象,而Student、Teacher类都是他的实例,所以结果如下
在这里插入图片描述
当然Type类型对象也有自己的类型对象指针,他指向自己
所以现在我们知道了,System.ObjectGetType方法返回存储在指定对象的类型对象指针成员中的地址,也就是说,GetType方法返回指向对象的类型对象指针
这样就可以判断系统中的任何对象了。
下面的运行结果可以验证
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值