CLR C#--类型基础

文章目录

类型

new

CLR 要求所有对象都用new操作符创建。以下代码展示了如何创建一个Employee对象:

Employee e = new Employee("ConstructorParaml");
  1. 堆上为类型分配字节数大小
  2. 从托管堆中分配类型要求的字节数,从而分配对象的内存,分配的所有字节都设为零(0)
  3. 初始化对象的“类型对象指针”和“同步块索引”成员。
  4. 调用类型的实例构造器,传递在new调用中指定的实参,最终调用System.Object的
    构造器,该构造器什么都不做,简单地返回。

new执行了所有这些操作之后,返回指向新建对象一个引用(或指针)。在前面的示例代码中,
该引用保存到变量e中,后者具有Employee类型。

is和as

在C#语言中进行类型转换的另一种方式是使用is操作符。is检查对象是否兼容于指定类型,
返回Boolean值true或false。注意,is操作符永远不抛出异常

Object o = new Object();
Boolean bl = (o is Object);                // bl 为 true. 
Boolean b2 = (o is Employee);           // b2 为 false.

如果对象引用null, is操作符总是返回false,因为没有可检查其类型的对象。 is操作符通常像下面这样使用:

if (o is Employee) { 
	Employee e = (Employee) o; 
}
  1. is操作符首先核实o是否兼容于Employee 类型–1次检查
  2. 如果是,在if语句内部转型时,CLR遍历继承层次结构,用每个基类型去核对指定的类型(Employee)o --2次检查

对性能有一定影响,C#专门提供了 as操作符, 目的就是简化这种代码的写法,同时提升其性能。

Employee e = o as Employee; 
if (e != null) {
	
}
  1. CLR核实o是否兼容于Employee类型;如果是,as返回对同一个对象的非null引用。如果o不兼容于Employee类型,as返回null。

注意,as操作符造成CLR只校验一次对象类型。if语句只检查e是否为nuU;这个检查的速度比校验对象的类型快得多。

栈空间用于向方法传递实参,方法内部定义的局部变量也在栈上。栈从高位内存地址向低位内存地址构建。
在这里插入图片描述

  1. M1方法 幵始执行时,它的“序幕”代码在线程栈上分配局部变量name的内存
  2. M1调用M2方法,将局部变量name作为实参传递。这造成name局部变量中的地
    址被压入栈。M2方法内部使用参数变量s标识栈位置另外,调用方法 时还会将“返回地址”压入栈。被调用的方法在结束之后应返回至该位置
  3. M1会返回到它的调用者。同样通过将CPU的指令指针设置成返回地址来实现
  4. 之后,调用Ml的方法继续执行Ml调用之后的代码

堆上所有对象都包含两个额外成员:类型对象指针和同步块索引。

internal class Manager : Employee {
	//...
}
internal class Employee {
	//非虚实例方法
	public Int32 GetYearsEmployed()
	{
		//....
	}
	//虚方法
	public virtual String GetProgressReport()
	{
		//....
	}
	public static  Employee Lookup(String name)
	{
		//....
	}
}

在这里插入图片描述
5. Employee 和 Manager 类型对象都有这两个成员。定义类型时,可在类型内部定义静态数据字段。为这些静态数 据字段提供支援的字节在类型对象自身中分配。每个类型对象最后都包含一个方法表。在
方法表中,类型定义的每个方法都有对应的记录项。
6. 当CLR确认方法需要的所有类型对象都已创建,M3的代码已经编译之后,就允许线程执 行M3的本机代码。M3的“序幕”代码执行时必须在线程栈中为局部变量分配内存,CLR自动将所有局部变量初始 化为null或0(零)。
7. M3执行代码构造一个Manager对象。这造成在托管堆创建Manager类型的一个实例(也就是一个Manager对象)在调用类型的构 造器(本质上是可能修改某些实例数据字段的方法)之前,CLR会先初始化同步块索引,并 将对象的所有实例字段设为nuU或0(零)。new操作符返回Manager对象的内存地址
8. 调用静态方法时,CLR会定位与定 义静态方法的类型对应的类型对象。然后,JIT编译器在类型对象的方法表中查找与被调用 方法对应的记录项,对方法进行J1T编译,再调用JIT编译好的代码。本例
假定Employee的Lookup方法要查询数据库来查找Joe。再假定数据库指出Joe是公司的 一名经理,所以在内部,Lookup方法在堆上构造一个新的Manager对象,用Joe的信息初始化它,返回该对象的地址。该地址保存到局部变量e中。
5. JIT编译器在类型对象的方法表中查找引用了被调用方法的记录项,对方法进行JIT 编译(如果需要的话),再调用JIT编译好的代码。本例假定Employee的GetYearsEmployed方法返回5,因为Joe已被公司雇用5年。这个整数保存到局部变量year中。
6. 调用Employee的虚实例方法GetProgressReport。调用虛实例方法时, JIT编译器要在方法中生成一些额外的代码;方法每次调用都会执行这些代码。这些代码首 先检查发出调用的变量,并跟随地址来到发出调用的对象。变量e当前引用的是代表“Joe” 的Manager对象。然后,代码检查对象内部的“类型对象指针”成员,该成员指向对象的 实际类型。然后,代码在类型对象的方法表中查找引用了被调用方法的记录项,对方法进行JIT编译(如果需要的话),再调用JIT编译好的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sufengmarket

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值