C#—装箱(boxing)与拆箱(unboxing)

   在了解装箱与拆箱之前,首先了解一下两种数据类型:值类型和引用类型。

一、值类型

  值类型就是一个包含实际数据的量。当定义一个值类型的变量时,C#会根据它所声明的类型,以堆栈方式分配一块大小相适应的存储区域给这个变量,对这个变量的读、写操作就直接在这块内存区域进行。

例如:

int INum=10;//分配一个32位内存区域给变量INum,并将10放入该内存区域

注意:

1、值类型是在柞中分配内存,在声明时初始化才能使用,不能为null。

2、值类型超出作用范围系统自动释放内存

3、主要由两类组成:结构、枚举(enum),结构分为:

       a、整型(Sbyte、Byte、Char、Short?Ushort、Int、Unit、Long、Ulong)

       b、浮点型(Float、Double)

       c、decimal

       d、bool

       e、用户定义的结构(struct)

二、引用类型

  引用类型的变量不存储它们所代表的实际数据,而是存储实际数据的引用。引用类型分两步创建:首先在堆栈上创建一个引用变量,然后在堆上上创建对象本身,再把这个内存的句柄(也是内存的首地址)赋给引用变量。

例如:

string s1,s2;
s1="a";s2=s1;

其中s1,s2是指向字符串的引用变量,s1的值是字符串“a”存放在内存的地址,这就是字符串的引用,两个引用变量之间的赋值,使s1、s2都是对“a”的引用。

注意:

1、引用类型在堆中分配内存,初始化时默认为null

2、引用类型通过垃圾回收机制进行回收

3、包括类、接口、委托、数组及内置引用类型object与string,其中object和string是两个比较特殊的类型。C#中,所有类型都是直接或间接从object继承的。可以将任何类型的值赋给object类型的变量。

4、堆和栈是两个不同的概念,在内存中存储位置也不同,堆一般用于存储可变长度的数据,按任意顺序和大小进行分配和释放内存,而栈一般一般用于存储固定长度的数据,按先后进出的原则存储数据项的一种数据结构。

三、装箱与拆箱

  值类型和引用类型之间的转换被称为装箱与拆箱。通过这个操作可以轻松实现值类型和引用类型的相互转换,任何类型的值最终都可以按照对象来处理。

1、装箱

  装箱是值类型转换为object类型,或者转换为由值类型所实现的任何接口类型。把一个值类型装箱就是创建一个对象并把值赋给对象。

例如:

int i=123; //把“123“赋给int型变量
object o=i; //装箱操作

2、拆箱

  拆箱是从object类型到值类型或从接口类型到实现该接口的类型的显示转换。取消装箱的步骤为:

(1)检查对象实例是否是给定的值类型的装箱值。(拆箱后没有转换成原类型,编译时不会出错,但运行会出错,所以一定要确保这一点。用GetType().ToString()判断时一定要使用类型全称,如:System.String而不要String)

(2)将该值从实例复制到值类型变量中

int i=123;  //把”123“赋给int型变量i
objecto=i; //装箱操作
int j=(int)o  //拆箱操作

  由于拆箱的过程中要对引用类型内存放的值进行检查,因此对于不兼容的类型转换将导致异常。例如:

int i=1;  //把”1“赋给int型变量;
object obj=i;  // 装箱操作
string j=(string) obj;  //类型不兼容

注意:当一个"装箱"操作把值类型转换为引用类型时,不需要显示地强制类型转换,而拆箱操作就把引用类型转换到值类型时,由于它可以强制转换到任何可以相兼容的值类型,所以必须显示地强制类型转换。

 

你可能感兴趣的:(C#—装箱(boxing)与拆箱(unboxing))