(CLR-Via-C#) 类型基础

时间:2023-03-08 23:03:32
(CLR-Via-C#) 类型基础
CLR要求每个类型最终都派生自System.Object

Object提供的公共方法:

  • Equals: 如果两个对象具有相同的值,就返回true
  • GetHashCode: 返回对象的哈希码
  • ToString:默认返回类型的完整名称(this.GetType().FullName)
  • GetType: 返回从type派生的一个实例

object的protected方法:

  • MemberwiseClone:这个非虚方法创建类型的新实例,并将新对象的实例字段设与this的字段完全一致
  • Finalize:在垃圾回收器判断对象应该作为垃圾回收之后。在对象的内存被实际回收之前,会调用这个虚方法。需要在回收内存钱执行清理工作的类型,应该重写该方法。

所有对象都需要使用new操作符,new的实际操作如下:

  1. 计算类型及其所有基类型定义的所有实例字段所需要的字节数。堆上哦度需要一些额外的开销成员(overhead成员)包括类型对象指针(type object pointer)和同步索引块(sync block index).CLR利用这些成员管理对象。额外的成员也要计入对象大小。
  2. 从托管堆中分配类型要求的字节数,从而分配对象的内存,分配的所有字节都设为0
  3. 初始化对象的“类型对象指针”和“同步索引块“成员
  4. 调用类型的实例构造器(构造函数),传递在new中指定的实参
类型转换

CLR重要的就是类型安全,所以不是所有的类型都能进行互相转换,首先说派生类和基类的转换。

提到继承的转换,第一个应该想到的就是里氏转换原则:

子类一定可以转换为父类,而父类不一定能转换成子类

熟悉一个异常InvalidCastException:

internal class Employee

{

……

}

internal class Manager:Employee

{

……

}

public class XXXX()

{

public void main()

{

Manager m =new Manager();

Test(m);

DataTime d=new DataTime ();

Test(d);

}

public void Test(Object o)

{

Employee e =(Employee) o;

}

}

以上,值得注意的是编译器都不会报错,但是实际代码段Test(d)运行时会报InvalidCastException。因为d是一个DateTime类型,自然可以隐式转换为Object,但是它不能转换为Employee,以后看见这个异常,应该觉得很眼熟才对。

然后涉及到is和as运算符的问题:

首先了解一下两个运算符:

is: 判断是否是某一个类型,返回true和false并用永不会抛出异常,但是它并不会将类型进行转换。

as: 尝试将类型进行相应的转换,如果失败返回null,也不会抛出任何异常。

使用方法,不做赘述,那么在进行类型转换操作时:

is: 只能先判断是否能够转换,再进行转换,相当于要运算两次

as:直接进行转换,转换失败则返回类,所以为了避免返回类型报NullReferenceException,对结果做一次非空判断即可,只用运算一次,自然效率高一些。