深入理解CLR (1)
深入理解CLR
第一章 类型基础
1. System.Object类型
所有类型都继承于System.Object,因此下面两种类型的定义方式是等价的。
//隐式从Object类继承
class Employee
{
}
//显式从Object类继承
class Employee: Object
{
}
除此之外,任何类型直接或间接继承于System.Object还可以保证任何类型的任何对象都有一组通用的方法,这些通用方法就是从System.Object类继承下来的。
2. 对象创建始末
CLR通过操作符new创建类型的实例(对象):
Employee emp = new Employee("constructor params");
这条语句创建了Employee类型的一个对象,并将指向该新建对象的引用存放在emp变量中。
下面是new操作符所作的工作:
1. 它计算类型及其所有基类型(最高至System.Object,虽然它没有定义自己的实例字段)中定义的所有实例字段需要的字节数。堆上每个对象都需要一些附加成员:类型对象指针和同步块索引。这些成员将由CLR用来管理对象,这些额外成员的字节数会加到对象大小上。
2. 它从托管堆中分配指定类型所需数量的字节来作为存储其对象的内存空间,分配的所有字节都置为0(二进制意义上的0)。
3. 初始化对象的附加成员。每一个对象都有两个附加成员,其中第一个成员为指向类型方法表的指针;第二个成员为同步块索引(注: CLR使用该成员来进行线程同步控制,该字段的某些位还用作垃圾收集时的标记,另外FCL中System.Object类型默认的GetHashCode方法也用到了该字段)。CLR使用这两个成员来管理对象实例。
4. 调用类型的构造函数,向其传入在new调用中指定的任何实参。大多数编译器会在构造函数中自动生成代码来调用其基类的构造函数。这样,最终会调用到System.Object的构造函数,该构造函数只是简单的返回。
new操作符执行了所有这些操作后,会返回对新创建的对象的一个引用(或指针)。
值得注意的是,new操作符没有相对应的delete操作符,换言之,没有办法显式释放为一个对象分配的内存,CLR采用了垃圾回收机制,能自动检测到一个对象不在被使用或访问,并自动释放对象内存。
[补充]
new操作符的用法:
1. 用于创建对象和调用其构造函数:
Employee emp = new Employee( );
2. 用于创建匿名类型的实例:
var query = from cust in customers
select new {Name = cust.Name, Address = cust.PrimaryAddress};
3. 用于调用值类型的构造函数:
int i = new int(); // 该语句效果等同于int i = 0;
注意:
(1)不能重载new运算符。
(2)如果new 运算符分配内存失败,将会引发OutOfMemoryException异常。