注:以下笔记全摘录自CLR via C# 3
1、所有类型都从System.Object派生:”运行时“要求每个类型最终都从System.Object派生。
2、System.Object提供了四个公共实例方法:
(1) Equals :如果两个对象具有相同的值,就返回true。
(2) GetHashCode
(3) ToString:该方法默认返回类型的完整名称(this.GetType().FullName)。然而,我们经常重写这个方法,使它返回一个String对象,其中包含对象状态的一个表示。例如,核心类型(比如Boolean和Int32)重写了这个方法,返回他们值的一个字符串表示。
(4) GetType:返回Type派生的一个对象的实例,指出调用GetType的那个对象是什么类型。返回的Type对象可以和反射类配合使用,从而获取与对象的类型有关的元数据信息。
3、System.Object的受保护方法:
(1) MemberwiseClone:这个非虚方法能创建一个类型的新实例,并将新对象的实例字段设与this对象的实例字段完全一致。返回的是对新实例的一个引用。
(2) Finalize:在垃圾回收器判断对象应该被作为垃圾回收之后,在对象的内存被实际回收之前,会调用这个虚方法。
4、CLR要求所有对象都用new操作符来创建。以下是new操作符所做的事情。
(1) 它计算类型及其所有基类型(一直到System.Object,虽然它没有定义自己的实例字段)中所有字段需要的字节数。堆上每个对象都需要一些额外成员,”类型对象指针“(type object pointer)和“同步块索引”(sync block index)。这些成员由CLR用于管理对象。这些额外成员的字节数会计入对象大小。
(2)它从托管堆中分配指定类型要求的字节数,从而分配对象的内存,分配的所有字节都设为零(0)。
(3)它初始化对象的”类型对象指针“和”同步块索引“成员。、
(4)调用类型的实例构造器,向其传入在对new的调用中指定的任何实参。
5、顺便说一句,没有和new操作符对应的delete操作符;换言之,没有办法显示释放为一个对象分配的内存。
6、CLR最重要的特性之一就是类型安全性。(其它的重要特性呢?)
7、使用C# 的is 和as操作符来转型。
(1)is :用于检查一个对象是否兼容于指定的类型,并返回一个Boolean值:true或false。注意:is操作符永远不会抛出异常。如果引用对象是null,is操作符总是返回false,因为没有可检查其类型的对象。
is操作符通常像下面这样使用(放到if判断里面)
if( o is Employee){ Employee e=(Employee ) o; //在剩下的代码用e }
这段代码,CLR会检查两次对象的类型;is 操作符首先核实o是否兼容于一个Employee类型。如果是,那么在if语句内部执行时,CLR再次核实o是否引用一个Employee。(类型检查增加了安全性,但是有性能损失)
(2)as:简化is的写法,同时提升性能(只校验一次)。as的工作方式和强制类型转换一样,只是它永远不会抛出异常,如果对象不能转型,结果就为null。所以,正确的做法是检查最终生成的引用是否为null。如果企图直接使用最终生成的引用,会抛出一个System.NullReferenceException异常,以下代码对此进行了演示:
Object o = new Object(); //新建一个Object对象 Employee e = o as Employee; // 将o转型为一个Employee //上述操作会失败,不会抛出异常,但e会被设为null e.ToString(); //访问e会抛出一个NullReferenceException异常
8、命名空间和程序集
命名空间(namespace)用于对相关的类型进行逻辑性分组,开发人员使用命名空间方便的定位一个类型。
在C#中,namespace的作用只是告诉编译器为源代码中出现的每个类型名称附加空间名称前缀,减少程序员的打字量。
命名空间和程序集的关系:
注意,命名空间和程序集不一定是相关的。特别是,同一个命名空间中各个类型可能是在不同程序集中实现的。例如,System.IO.FileStream类型是在MSCorLib.dll程序集中实现的,儿System.IO.FileSystemWatch类型是在System.dll程序集中实现的。
在一个程序集中,也可能包含不同命名空间中的类型。例如,System.Int32和System.Text.StringBuilder类型都在MSCorbLic.dll中。