OBJECT类型

object(System.Object)是所有类型的终极父类。
所有类型都可以向上转换为object。

例子

  1. // Stack(栈)后进先出
  2. public class Stack
  3. {
  4. int position;
  5. object[] data = new object[10];
  6. public void Push(object obj) => data[position++] = obj;
  7. public object Pop() => data[--position];
  8. }
  9. public class program
  10. {
  11. public static void Main()
  12. {
  13. Stack stack = new Stack();
  14. stack.Push("sausage");
  15. string s = (string)stack.Pop(); //向下转换,所以要显示转换
  16. System.Console.WriteLine(s); // print: sausage
  17. }
  18. }

OBJECT

object是引用类型
但值类型可以转化为object,反之亦然。(类型统一)

  1. stack.Push(3);
  2. int three = (int)stack.Pop();

在值类型和object之间转化的时候,CLR必须执行一些特殊的工作,以弥合值类型和引用类型之间语义上的差异,这个过程就叫做装箱和拆箱。

装箱

装箱就是把值类型的实例转化为引用类型实例的动作
装箱的目标引用类型可以使object,有可以是某个接口

  1. int x = 9;
  2. object obj = x; // Box the int

拆箱

拆箱正好相反,把那个对象转化为原来的值类型

  1. int y = (int)obj; // Ubox the int

拆箱需要显示的转换
在拆箱时运行时会检查这个值类型和object对象的真实类型是否匹配
如果不匹配就抛出**InvalidCastException**

  1. object obj = 9; //9是int类型
  2. long x =(long)obj;
  3. //InvalidCastException
  4. object obj = 9;
  5. long x =(int)obj; //成功,然后进行隐式转换为long
  6. object obj = 3.5; //3.5是double类型
  7. int x =(int)(double)obj; //x现在是3

注意

装箱对于类型统一是非常重要的。但是系统不够完美
数组和泛型只支持引用转换,不支持装箱。

  1. object[] a1= new string[3] //Legal
  2. object[] a2 = new int[3]; //Error

装箱拆箱的复制

装箱会把值类型的实例复制到一个新的对象
拆箱会把这个对象的内容在复制给一个值类型的实例

  1. int i = 3;
  2. object boxed = i;
  3. i = 5;
  4. System.Console.WriteLine(boxed); // 3

静态和运行时类型检查

C#的程序既会做静态的类型检查(编译时),也会做运行时的类型检查(CLR)
静态检查:不经过程序的情况下,让编译器保证你程序的正确性

  1. int x ="5"; //Error

运行时的类型检查由CLR执行,发生在向下的引用转换或拆箱的时候。

  1. object y = "5";
  2. int z = (int)y; //Runtime error,downcase failed

运行时检查之所以可以行因为:每个heap上的对象内部都存储了一个类型token。这个token可以通过调用调用object的GetType()方法来获取。

GETTYPE方法与TYPEOF操作符

所有C#的类型在运行时都是以System.Type的实例来展现的
两种方式可以获得System.Type对象:
在实例上调用GetType()方法
在类型名上使用typeof操作符
GetType是在运行时被算出的
typeof是在编译时就被算出(静态)(当涉及到泛型类型参数时,它是由JIT编译器来解析的)

SYSTEM.TYPE

System.Type的属性有:类型的名称,Assembly,基类等等。。
未命名图片.png

TOSTRING方法

  • Tostring()方法返回一个类型实例的默认文本表示
  • 所有的内置类型都重写了该方法
    • int x = 1;
    • string s = x.Tostring(); //s is “1”
  • 可以在自定义的类型上重写Tostring()方法
  • 如果你不重写该方法,那就会返回该类型的名称

    1. public class Test
    2. {
    3. public static void Main()
    4. {
    5. Panda p = new Panda { Name = "Hello" };
    6. System.Console.WriteLine(p.ToString()); //Hello
    7. }
    8. }
    9. public class Panda
    10. {
    11. public string Name;
    12. public override string ToString() => Name;
    13. }
  • 当你调用一个被重写的object成员的时候,例如在值类型上直接调用Tostring()方法,这个时候就不会发生装箱操作

  • 但是如果你进行了转换,那么装箱操作就会发生
    1. int x= 1;
    2. string s = x.Tostring(); // 不发生装箱
    3. object box = x;
    4. string s2 = box.Tostring(); // 发生装箱

    OBJECT的成员列表

    未命名图片.png