从内存执行的角度来看,值类型的内存分配在线程的堆栈上,而引用类型的内存分配在托管堆上。因此从值类型向引用类型的转换,势必牵涉到数据的拷贝与指针引用等操作。

  装箱操作,大致过程为:在托管堆中分配新对象的内存,将值类型的字段拷贝到该内存中,然后返回该对象的地址,这样就完成了从值类型到引用类型的转变;拆箱操作,则是获取已装箱对象中来自值类型部分字段的地址。装箱与拆箱并非完全对称的互逆操作,拆箱并不包含字段的拷贝。

  概念雷区:

  1. 装箱与拆箱不是完全对等的互逆操作。从内存的角度上看,拆箱的性能开销远小于装箱,只是在实际的执行中,拆箱之后常伴随着字段的拷贝,以c#为例,编译器总是自动产生拆箱之后的字段拷贝。
  2. 只有被装箱过的对象才能被拆箱,非所有的引用类型。将非装箱而来的引用类型强制转换为值类型,会抛出InvalidCastException异常。

分拆

  值类型,提供了轻量型的数据结构,具有较少的内存开销,对系统性能有明显的作用。而缺点是:缺省方法表指针,因为无法在期望System.Object或其继承类的方法上调用值类型。

  装箱过程解析

  1. 内存分配:在托管堆中分配内存空间,内存大小为欲装箱值类型的大小加上其他额外的内存空间,主要包括方法表指针与SyncBlockIndex,此两个成员用于CLR管理引用类型对象。
  2. 实例拷贝:将值类型的字段拷贝到新分配的内存中去
  3. 地址返回

  拆箱过程解析

  1. 实例检查:首先检查是否是null,若是抛出NullReferenceException;若非,检查对象实例,确保是给定值类型的装箱值,并且保证拆箱后的类型为原来的同一类型,否则会抛出InvalidCastException
  2. 指针返回:返回已经装箱对象中属于原值类型部分字段的地址。而附加成员:方法表指针与SyncBlockIndex对该指针是不可见的。
  3. 字段拷贝:将托管堆中实例的字段拷贝到线程的堆栈中。

性能

  1. 在实际的项目中留意发生隐式装箱的可能,并提供相应的多个重载方法来避免装箱的发生。
  2. 装箱与拆箱经常是以隐式发生的,在系统中显式的实现装箱操作,是提高性能的较好选择
  3. 泛型能有效减少了装箱与拆箱的发生,大大提高了系统的性能与稳定。

应用

  1. ArrayList与Array
  2. Hashtable
  3. 枚举
    枚举类型为典型的.Net值类型,可以被装箱为System.Object,System.ValueType和System.Enum,以及System.Enum实现的三个接口类型System.IComparable,System.IConvertible,System.IFormattable
  4. 关注不经意的隐式转换
     public static void Main()
    {
    int i = ;
    //装箱
    i.GetType();
    //未装箱
    i.ToString();
    //显式装箱
    object o = i;
    Hashtable ht = new Hashtable();
    ht.Add("One", o);
    ht.Add("Two", o);
    }

    GetType方法由System.Object类型提供,因此值类型调用时必须执行装箱操作;而ToString方法则由int类型覆盖,因此不会装箱。Hashtable的Add方法接受System.Object类型的参数,因此通过显式的类型转换来减少隐式的装箱操作。

最新文章

  1. 国际化(Internationalization)
  2. Ajax表单异步上传(包括文件域)
  3. Azure HDInsight 和 Spark 大数据实战(二)
  4. Spring 4.0.2 学习笔记(1) - 最基本的注入
  5. asp.net mvc开发的社区产品相关开发文档分享
  6. QML鼠标事件实现变色矩形
  7. 运行第一个Hadoop程序,WordCount
  8. Petya勒索病毒疫苗出现,分分钟让电脑对病毒免疫
  9. 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析
  10. 你考虑清楚了吗就决定用 Bootstrap ?
  11. Spring MVC 返回Json数据环境记录
  12. Django 2.0 新款URL配置详解
  13. Webapi 跨域 解决解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource 问题
  14. SpringBoot使用数据库
  15. python第三十五天-----作业完成--学校选课系统
  16. os 模块 和 os模块下的path模块
  17. altera FIFO知识点
  18. Git 学习之Git 基础(二)
  19. Nginx代理
  20. Word文档发布到CSDN博客

热门文章

  1. Synopsys EDA工具在LinuxMint 18(Ubuntu 16.04.2)安装注意事项
  2. SqlMap之数据库操作语句总结
  3. 流畅的python第十二章继承的优缺点学习记录
  4. 如何修改JComboBox的宽度
  5. Win7如何重建桌面图标缓存
  6. HDU 1253 胜利大逃亡 NYOJ 523【BFS】
  7. 【转】Struts2 和 Spring MVC对比
  8. 《深入浅出pig系列之中的一个》pig-0.12.0-cdh5.1.2的安装与执行
  9. [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第九章 内存管理
  10. 运用Unity结合PolicyInjection实现拦截器[结合操作日志实例]