object类型
- object(System.Object)是所有类型的终极父类。
- 所有类型都可以向上转换为object。
后进先出,压栈 出栈
object是引用类型
- 但值类型可以转化为object,反之亦然。(类型统一)
stack.Push(3);
int three = (int) stack.Pop();
在值类型和object之间转化的时候,CLR必须执行一些特殊的工作,以弥合值类型和引用类型之间语义上的差异,这个过程就叫做装箱和拆箱。
装箱
- 装箱就是把值类型的实例转化为引用类型实例的动作
- 目标引用类型可以是object,也可以是某个接口
拆箱
- 拆箱正好相反,把那个对象转化为原来的值类型
拆箱需要显式的转换。
拆箱
- 运行时会检查这个值类型和object对象的真实类型是否匹配
- 如果不匹配就抛出InvalidCastException
注意
- 装箱对于类型统一是非常重要的。但是系统不够完美
- 数组和泛型只支持引用转换,不支持装箱
装箱拆箱的复制
- 装箱会把值类型的实例复制到一个新的对象
- 拆箱会把这个对象的内容再复制给一个值类型的实例
静态和运行时类型检查
- C#的程序既会做静态的类型检查(编译时),也会做运行时的类型检查(CLR)
- 静态检查:不运行程序的情况下,让编译器保证你程序的正确性
int x = "5";
运行时的类型检查由CLR执行,发生在向下的引用转换或拆箱的时候。
- 运行时检查之所以可行是因为:每个在heap上的对象内部都存储了一个类型token。这个token可以通过调用object的GetType()方法来获取
GetType方法与typeof操作符
- 所有C#的类型在运行时都是以System.Type的实例来展现的
- 两种方式可以获得System.Type对象:
- 在实例上调用GetType()方法
- 在类型名上使用typeof操作符。
- GetType是在运行时被算出的
- typeof 是在编译时被算出(静态)(当涉及到泛型类型参数时,它是由JIT编译器来解析的)
System.TYPE
- System.Type的属性有:类型的名称,Assembly,基类等等。
ToString方法
- ToString()方法会返回一个类型实例的默认文本表示
- 所有的内置类型都重写了该方法
- 可以在自定义的类型上重写ToString()方法
- 如果你不重写该方法,那就会返回该类型的名称
- 当你调用一个被重写的object成员的时候,例如在值类型上直接调用ToString()方法,这时候就不会发生装箱操作
- 但是如果你进行了转换,那么装箱操作就会发生