装箱与拆箱的走走停停

上一篇简单述说了值类型与引用类型的关系,那么不能不说说值类型的拆箱与装箱:

将值类型装箱就相当于把它包装起来给人看,"你瞧,我现在是引用类型了",顾名思义拆箱就是将包装卸下来"其实我是值类型"。

   在将值类型利用装箱机制打包成引用时他要进行许多的打扮:

      1.首先要给他一个空间(在托管堆中分配内存),多大呢,要必须要容得下包装所需要的物件化妆品之类的(各自段所需的内存量),此外还要有专家设计师吧(类型对象指针和同步块索引两个额外的成员);

      2.空间有了,他就要开始将自己的东西和物件搬过来(只类型的字段复制到新分配的堆内存);

      3.一切准备就绪,不过此时出了意外,他被人顶替冒充了,而冒充它的那个人很清楚这个房间的位置(返回对象地址,改地址就是对象引用)。

上面解释可能会有点牵强,给个例子一目了然:

 1 struct Point{public int x,y;}
 2 public sealed class Program{
 3     public static void Main()
 4      {
 5        ArrayList a = new ArrayList();
 6        Point p;
 7        p.x=1;p.y=1;
 8        a.Add(p);
 9      }
10 }

最简单不过的代码了,由于Add()方法参数是Object类型,所以在执行时要进行一次装箱操作:Point值类型实例p中的字段会复制到新分配的Point对象中,已装箱的Point对象的地址返回并传给Add方法,需要说明的是Point对象此时是引用类型存在于堆中,Point值类型变量p可被重用,a已经不知道他的任何事情,由此可见已装箱值类型生存期超过了未装箱值类型的生存期。

-------------------------------------------------------------------------------

接下来说说拆箱:

  紧接上段代码,如若Point p = (Point)a[0];代码执行时,就进行了一次拆箱:

  一个人他知道了那个房间的地址,他把东西都要了回来,而东西可能已经变了(拆箱不是简单的装箱逆过程,它的代价比装箱要低,拆箱就是获取指针的过程,该指针指向包含在一个对象中的原始值类型(数据字段),指针指向的是已装箱实例中未装箱的部分,不要求在内存中复制任何字节);

  拆箱时要注意:1.包含"对已装箱类型实例的引用"的变量为null时,会抛出异常(他都没有房间,也没有物件,你找个P啊)

         2.如果引用的对象不是所需值类型的已装箱实例,抛出异常(张三的东西,李四来要,对方能给吗);

--------------------------------------------------------------------------------

下面来做个脑筋急转弯:

1 public static void Main(){
2         int v=5;
3         Object o = v;
4         v=123;
5         Console.WriteLine(v+","+(int)o);
6 }

问:上面代码发生了多少次装箱?想好在打开。。。

三次,一次很好理解,剩下的两次,对比Console.WriteLine参数即可理解

部分内容参考自《CLR C#》

   

时间: 2024-10-18 20:41:09

装箱与拆箱的走走停停的相关文章

C#装箱与拆箱的研究

在对这个问题展开讨论之前,我们不妨先来问这么几个问题,以系统的了解我们今天要探究的主题. 观者也许曾无数次的使用过诸如System.Console类或.NET类库中那些品种繁多的类.那么,我想问的是它们究竟源自何处?C#又是如何联系它们?有没有支持我们个性化扩展的机制或类型系统?又有哪些类型系统可供我们使用呢?如果我们这些PL们连这些问题都不知其然,更不知其所以然的话,C#之门恐怕会把我们拒之门外的. 那就让我们先停停手中的活儿,理理头绪,对作为.NET重要技术和基础之一的CTS(Common

深入剖析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中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱

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