OBJECT类型
object(System.Object)是所有类型的终极父类。
所有类型都可以向上转换为object。
例子
// Stack(栈)后进先出
public class Stack
{
int position;
object[] data = new object[10];
public void Push(object obj) => data[position++] = obj;
public object Pop() => data[--position];
}
public class program
{
public static void Main()
{
Stack stack = new Stack();
stack.Push("sausage");
string s = (string)stack.Pop(); //向下转换,所以要显示转换
System.Console.WriteLine(s); // print: sausage
}
}
OBJECT
object是引用类型
但值类型可以转化为object,反之亦然。(类型统一)
stack.Push(3);
int three = (int)stack.Pop();
在值类型和object之间转化的时候,CLR必须执行一些特殊的工作,以弥合值类型和引用类型之间语义上的差异,这个过程就叫做装箱和拆箱。
装箱
装箱就是把值类型的实例转化为引用类型实例的动作
装箱的目标引用类型可以使object,有可以是某个接口
int x = 9;
object obj = x; // Box the int
拆箱
拆箱正好相反,把那个对象转化为原来的值类型
int y = (int)obj; // Ubox the int
拆箱需要显示的转换
在拆箱时运行时会检查这个值类型和object对象的真实类型是否匹配
如果不匹配就抛出**InvalidCastException**
object obj = 9; //9是int类型
long x =(long)obj;
//InvalidCastException
object obj = 9;
long x =(int)obj; //成功,然后进行隐式转换为long
object obj = 3.5; //3.5是double类型
int x =(int)(double)obj; //x现在是3
注意
装箱对于类型统一是非常重要的。但是系统不够完美
数组和泛型只支持引用转换,不支持装箱。
object[] a1= new string[3] //Legal
object[] a2 = new int[3]; //Error
装箱拆箱的复制
装箱会把值类型的实例复制到一个新的对象
拆箱会把这个对象的内容在复制给一个值类型的实例
int i = 3;
object boxed = i;
i = 5;
System.Console.WriteLine(boxed); // 3
静态和运行时类型检查
C#的程序既会做静态的类型检查(编译时),也会做运行时的类型检查(CLR)
静态检查:不经过程序的情况下,让编译器保证你程序的正确性
int x ="5"; //Error
运行时的类型检查由CLR执行,发生在向下的引用转换或拆箱的时候。
object y = "5";
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,基类等等。。
TOSTRING方法
- Tostring()方法返回一个类型实例的默认文本表示
- 所有的内置类型都重写了该方法
- int x = 1;
- string s = x.Tostring(); //s is “1”
- 可以在自定义的类型上重写Tostring()方法
如果你不重写该方法,那就会返回该类型的名称
public class Test
{
public static void Main()
{
Panda p = new Panda { Name = "Hello" };
System.Console.WriteLine(p.ToString()); //Hello
}
}
public class Panda
{
public string Name;
public override string ToString() => Name;
}
当你调用一个被重写的object成员的时候,例如在值类型上直接调用Tostring()方法,这个时候就不会发生装箱操作
- 但是如果你进行了转换,那么装箱操作就会发生
int x= 1;
string s = x.Tostring(); // 不发生装箱
object box = x;
string s2 = box.Tostring(); // 发生装箱
OBJECT的成员列表