C#装箱与拆箱

装箱:将值类型转换成引用类型的的一种机制。

拆箱:获取已装箱对象中被装箱字段的地址;值得注意的是拆箱并不是装箱的逆过程。

如果你不知道怎么看自己的代码是不是发生了装箱,一个简单的方法就是通过visual studio自带的IL反编译工具查看,

如下面的代码,大家可以在IL指令中去找box,如果哪里出现它,就说明这里发生了装箱

当然,上面的代码大家一般不会这么写,这里只是告诉大家怎么去自己的代码你去找装箱发生的地方。

我把上面的代码注释了,重写了一行代码,重新打开IL反编译工具,大家看看有什么不同?

这次为啥没有box了呢?因为代码里没发生装箱。为啥呢?因为Console.WriteLine()方法有重载的方法太多了,其中方法签名中就有包含Int32的,所以写代码的时候一定要注意参数的类型。许多看似差不多的代码,背后往往暗藏玄机。

那么怎么知道代码中有没有发生拆箱呢?

同样的可以在IL指令中找到unbox

现在大家都知道代码中有没有发生装/拆箱了,那装/拆箱的过程中都干了哪些事呢?

1        static void Main(string[] args)
2         {
3             Int32 number=5;
4             Object o = number;//装箱
5             number = 10;
6             Console.WriteLine(number);
7             number = (Int32)o;//拆箱
8             Console.WriteLine(number);
9         }

装箱:

1、在堆中开辟一片空间,这片空间的大小是number的值所占内存的大小加上托管堆对象的两个额外成员(类型对象指针和同步块索引)。

2、将number的值复制到刚才分配的空间中。

3、返回堆中这个对象的对象的引用地址。

然后对象o就拿到了这个地址,当然这时候已经完成了装箱。

从这个过程中,可以看出,只要发生装箱,就需要去堆内存中开辟空间,再把字段赋值过去,这就是为什么装箱会造成内存消耗,影响性能的原因,所以应该在程序中尽可能的避免写发生装箱的代码。当然该写的时候就得写。

拆箱:

在文章开头的时候其实已经说明了拆箱的过程,拆箱就是在堆中找到原始值类型的地址的过程。也就是说它没有进行值的复制,所以相对来说比装箱消耗性能要小得多了。

拆箱的时候有一个知识点也是需要注意的,就是你把什么样的值类型装箱了拆的时候需要把他拆成什么样的类型,否则就会发生InvalidCastException异常。

最后,你能看出下面的代码发生了几次装箱了么?不注意的话,好多码崽经常会写出下面的代码哦

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Point p = new Point(2, 5);
 6             Console.WriteLine(p);
 7             Console.WriteLine("{0};{1}", p, p);
 8             Console.WriteLine(p.ToString());
 9             Console.WriteLine(p.GetType());
10         }
11     }
12
13     struct Point
14     {
15         readonly Int32 x;
16         readonly Int32 y;
17         public Point(Int32 x, Int32 y)
18         {
19             this.x = x;
20             this.y = y;
21         }
22         public override string ToString()
23         {
24             return string.Format("{0}-{1}", x, y);
25         }
26     }
时间: 2024-11-08 21:33:15

C#装箱与拆箱的相关文章

深入剖析Java中的装箱和拆箱

阅读目录 一.什么是装箱?什么是拆箱?二.装箱和拆箱是如何实现的三.面试中相关的问题 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 回到顶部 一.什么是装箱?什么是拆箱? 我们知道 Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE5之前,如果要生成

转 C# 装箱和拆箱[整理]

1.      装箱和拆箱是一个抽象的概念 2.      装箱是将值类型转换为引用类型 :拆箱是将引用类型转换为值类型       利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来 例如: int val = 100; object obj = val; Console.WriteLine (“对象的值 = {0}", obj); 这是一个装箱的过程,是将值类型转换为引用类型的过程 int val = 100; object obj =

【c#】装箱与拆箱

从内存执行的角度来看,值类型的内存分配在线程的堆栈上,而引用类型的内存分配在托管堆上.因此从值类型向引用类型的转换,势必牵涉到数据的拷贝与指针引用等操作. 装箱操作,大致过程为:在托管堆中分配新对象的内存,将值类型的字段拷贝到该内存中,然后返回该对象的地址,这样就完成了从值类型到引用类型的转变:拆箱操作,则是获取已装箱对象中来自值类型部分字段的地址.装箱与拆箱并非完全对称的互逆操作,拆箱并不包含字段的拷贝. 概念雷区: 装箱与拆箱不是完全对等的互逆操作.从内存的角度上看,拆箱的性能开销远小于装箱

《Java中的自动装箱和拆箱功能.》

1 //Java中的自动装箱和拆箱功能. 2 class AutoboxingUnboxing 3 { 4 public static void main(String[] args) 5 { 6 //直接把一个基本类型变量赋给Interger对象. 7 Integer inObj = 5; 8 Object inObj1 = 6; 9 //直接把一个boolean类型的变量赋给一个Object类型的变量. 10 Object boolObj = true; 11 //直接把Integer对象赋

Java中的装箱与拆箱

在J2SE5.0后推出了自动装箱和拆箱的功能,以提高我们的开发效率,然而自动装箱和拆箱实际上是通过编译器来支持的(并非语言本身,或者说虚拟机),因而这种支持也隐藏了部分内部实质,再加上某些类的优化(比如Integer里面的缓存等,参看关于缓存节),就更加容易在特定的环境下产生问题,并且如果不知道原来还无法调试.以下先是简单的介绍了编译器对装箱和拆箱的实现,并根据实现简单介绍一下可能会遇到的几个问题. 在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integ

值类型的装箱和拆箱

在CLR中为了将一个值类型转换成一个引用类型,要使用一个名为装箱的机制. 下面总结了对值类型的一个实例进行装箱操作时内部发生的事: 1)在托管堆中分配好内存.分配的内存量是值类型的各个字段需要的内存量加上托管堆上的所有对象都有的两个额外成员(类型对象指针和同步块索引)需要的内存量. 2)值类型的字段复制到新的分配的堆内存. 3)返回对象的地址.现在,这个地址是对一个对象的引用,值类型现在是一个引用类型. 拆箱不是直接将装箱过程倒过来.拆箱的代价比装箱低得多.拆箱其实就是一个获取一个指针的过程,该

.NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱 (转)

作者: Edison Chou  来源: 博客园  发布时间: 2014-09-03 15:59  阅读: 318 次  推荐: 2   原文链接   [收藏] 原文作者:Shivprasad koirala 英文原文:Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing 一.概述 本文会阐述六个重要的概念:堆.栈.值类型.引用类型.装箱和拆箱.本文首先会通过阐述当

.NET中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱

内容导读 概述 当你声明一个变量背后发生了什么? 堆和栈 值类型和引用类型 哪些是值类型,哪些是引用类型? 装箱和拆箱 装箱和拆箱的性能问题 一.概述 本文会阐述六个重要的概念:堆.栈.值类型.引用类型.装箱和拆箱.本文首先会通过阐述当你定义一个变量之后系统内部发生的改变开始讲解,然后将关注点转移到存储双雄:堆和栈.之后,我们会探讨一下值类型和引用类型,并对有关于这两种类型的重要基础内容做一个讲解. 本文会通过一个简单的代码来展示在装箱和拆箱过程中所带来的性能上的影响,请各位仔细阅读. 二.当你

深入剖析Java中的装箱和拆箱(转)

自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 二.装箱和拆箱是如何实现的 三.面试中相关的问题 一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE

java自动装箱与拆箱

基本数据(Primitive)类型的自动装箱(autoboxing).拆箱(unboxing)是J2SE 5.0提供的新功能,跟泛型.变长参数等一样,这也是一颗"语法糖",之前介绍jvm早期优化的时候说过,语法糖对运行期的代码没有任何影响,其目的仅仅是方便程序员使用,所有语法糖编译后都将会还原成基础语法.这次介绍的自动装箱和拆箱也不例外.看下头的例子: public class Demo { public static void main(String[] args) { Intege