• 装箱与拆箱的走走停停


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

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

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

          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参数即可理解
    View Code

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

       

  • 相关阅读:
    CSS属性选择器
    CSS基本选择器
    CSS的引入方式
    CSS
    228.4.flask试图
    227.3.flask路由
    225.1.flask初体验
    226.2.flask配置文件
    229.5.flask请求和相应
    230.6.flask模板
  • 原文地址:https://www.cnblogs.com/mjys-gh/p/4989718.html
Copyright © 2020-2023  润新知