C# - 深入理解C#的装箱和拆箱

转载 2016年08月31日 11:28:19

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。

1.装箱在值类型向引用类型转换时发生
2.拆箱在引用类型向值类型转换时发生

光上述两句话不难理解,但是往深处了解,就需要一些篇幅来解释了。

我们先看装箱时都会发生什么事情,下面是一行最简单的装箱代码

object obj = 1;

这行语句将整型常量1赋给object类型的变量obj; 众所周知常量1是值类型,值类型是要放在栈上的,而object是引用类型,它需要放在堆上;要把值类型放在堆上就需要执行一次装箱操作。

这行语句的IL代码如下,请注意注释部分说明:

.locals init (
  [0] object objValue
) //以上三行IL表示声明object类型的名称为objValue的局部变量
IL_0000: nop
IL_0001: ldc.i4.s 9 //表示将整型数9放到栈顶
IL_0003: box [mscorlib]System.Int32 //执行IL box指令,在内存堆中申请System.Int32类型需要的堆空间
IL_0008: stloc.0 //弹出堆栈上的变量,将它存储到索引为0的局部变量中

以上就是装箱所要执行的操作了,执行装箱操作时不可避免的要在堆上申请内存空间,并将堆栈上的值类型数据复制到申请的堆内存空间上,这肯定是要消耗内存和cpu资源的。我们再看下拆箱操作是怎么回事:

请看下面的C#代码:

object objValue = 4;
int value = (int)objValue;

上面的两行代码会执行一次装箱操作将整形数字常量4装箱成引用类型object变量objValue;然后又执行一次拆箱操作,将存储到堆上的引用变量objValue存储到局部整形值类型变量value中。

同样我们需要看下IL代码:

.locals init (
  [0] object objValue,
  [1] int32 'value'
) //上面IL声明两个局部变量object类型的objValue和int32类型的value变量
IL_0000: nop
IL_0001: ldc.i4.4 //将整型数字4压入栈
IL_0002: box [mscorlib]System.Int32  //执行IL box指令,在内存堆中申请System.Int32类型需要的堆空间
IL_0007: stloc.0 //弹出堆栈上的变量,将它存储到索引为0的局部变量中
IL_0008: ldloc.0 //将索引为0的局部变量(即objValue变量)压入栈
IL_0009: unbox.any [mscorlib]System.Int32 //执行IL 拆箱指令unbox.any 将引用类型object转换成System.Int32类型
IL_000e: stloc.1 //将栈上的数据存储到索引为1的局部变量即value

拆箱操作的执行过程和装箱操作过程正好相反,是将存储在堆上的引用类型值转换为值类型并给值类型变量。

装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以在c# 2.0之后引入了泛型来减少装箱操作和拆箱操作消耗。

下一篇我们看下使用泛型和不使用泛型情况下的装箱拆箱情况。

深入理解C#的装箱和拆箱、使用非泛型集合时引发的装箱和拆箱操作

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。  1. 装箱在值类型向引用类型转换时发生 2. 拆箱在引用类型向值类型转换时发生 光上述两句话不难理解,但是往深处了...
  • pengpegV5yaya
  • pengpegV5yaya
  • 2016年03月16日 23:02
  • 1581

C#--三行代码带你理解神秘的拆箱和装箱

一、在说拆箱和装箱之前的准备知识首先,我们需要知道c#中有两种类型:值类型和引用类型 名称 值类型 引用类型 表示类型 基本类型 类,数组,接口 ,C#特有的委托. 存储内容...
  • qq_32452623
  • qq_32452623
  • 2016年12月29日 17:22
  • 2994

C#装箱和拆箱(Boxing 和 UnBoxing)

1、什么是装箱和拆箱? 简单来说:       装箱是将值类型转换为引用类型 ;拆箱是将引用类型转换为值类型。(网上广为流传)  C#中值类型和引用类型的最终基类都是Object类型(它本身是一个引用...
  • qiaoquan3
  • qiaoquan3
  • 2016年05月17日 21:44
  • 2961

简述:C# 装箱和拆箱

一、概念简述: 在装箱拆箱之前简单说一下值类型、引用类型: 值类型:原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Doub...
  • u014076894
  • u014076894
  • 2015年04月16日 13:35
  • 1073

C# - 再谈C#的装箱和拆箱

上一篇写了一下装箱拆箱的定义和IL分析,这一篇我们看下使用泛型和不使用泛型引发装箱拆箱的情况 1. 使用非泛型集合时引发的装箱和拆箱操作  看下面的一段代码: 1 2 3 ...
  • honey199396
  • honey199396
  • 2016年08月31日 11:35
  • 533

.NET的装箱与拆箱内幕

装箱与拆箱是.NET中非常重要的概念。 装箱是将值类型转换成引用类型,或者是实现了接口的值类型。装箱将数据存储的空间由Thread stack转存到了Managed Heap中。凡是在Managed ...
  • xxdddail
  • xxdddail
  • 2014年07月04日 16:49
  • 1606

装箱和拆箱 VS 显示转换和隐式转换

一:显示转换和隐式转换 XmlDocument继承 XmlNode,把父类 XmlNode转换为子类对象需要 显示转化也就是强制转换; 子类转换为父类,自动就隐式转换了。比如说,香蕉是水果,把香蕉...
  • wangsen2235068
  • wangsen2235068
  • 2011年08月29日 17:13
  • 1671

值类型和引用类型间的转换-装箱和拆箱

装箱(Boxing)和拆箱(Unboxing)是C#类型系统中重要的概念。它允许将任何类型的数据转换为对象,同时也允许任何类型的对象转换到与之兼容的数据类型。 1.装箱 装箱转换是指将一个值类型的数据...
  • Gary_888
  • Gary_888
  • 2016年05月16日 13:45
  • 980

C# 装箱与拆箱

装箱是将值类型转换为引用类型 ;拆箱是将引用类型转换为值类型   利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来  例如:  int ...
  • qq_28270231
  • qq_28270231
  • 2015年07月31日 09:15
  • 250

C#泛型List< >集合:创建、与数组转换,记录运行时间、装箱与拆箱、dictionary

List  li=new List();// 创建泛型集合 与int数组转换             li.Add(2);             // 泛型集合中一个特点是可以转成数组     ...
  • yanhuatangtang
  • yanhuatangtang
  • 2017年05月27日 15:35
  • 348
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C# - 深入理解C#的装箱和拆箱
举报原因:
原因补充:

(最多只允许输入30个字)