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

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

  概念雷区:

  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类型的参数,因此通过显式的类型转换来减少隐式的装箱操作。

【c#】装箱与拆箱的更多相关文章

  1. C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱

    一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...

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

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

  3. Java暗箱操作之自动装箱与拆箱

    我以前在写Android项目的时候,估计写得最多最熟练的几句话就是: List<Integer> list = new ArrayList<Integer>(); list.a ...

  4. java 自动装箱自动拆箱

    1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...

  5. Java 自动装箱与拆箱

    Java 自动装箱与拆箱(Autoboxing and unboxing)   什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供 ...

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

    作者: Edison Chou  来源: 博客园  发布时间: 2014-09-03 15:59  阅读: 318 次  推荐: 2   原文链接   [收藏]   原文作者:Shivprasad k ...

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

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

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

    深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...

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

    1.      装箱和拆箱是一个抽象的概念 2.      装箱是将值类型转换为引用类型 :拆箱是将引用类型转换为值类型       利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的 ...

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

    //Java中的自动装箱和拆箱功能. class AutoboxingUnboxing { public static void main(String[] args) { //直接把一个基本类型变量 ...

随机推荐

  1. 关于Java设计模式的一些概况

    设计模式(Design pattern)在软件行业一直都扮演着很重要的角色.最近感觉自己对设计模式的知识有些遗忘了,虽然以前也看了很多,但是坦白说,其实并没有怎么理解.基本还是为了应付面试.然后,在工 ...

  2. socket连接和http连接的区别

    socket连接和http连接的区别 HTTP协议:简单对象访问协议,对应于应用层  ,HTTP协议是基于TCP连接的 tcp协议:    对应于传输层 ip协议:     对应于网络层 TCP/IP ...

  3. Android源代码编译apk导入第三方包报错

    报错内容例如以下: make: *** 没有规则能够创建"out/target/common/obj/APPS/ AndroidWFS_intermediates/classes-full- ...

  4. (转)intellij idea svn 修改文件后,父文件夹也标注修改

    svn文件修改后,默认只有当前文件更改而父文件没有标注,很不直观:查了一顿后,发现,可以设置: File—->settings—->version control—–>勾选show ...

  5. python处理csv

    python处理csv 学习了:https://blog.csdn.net/qq_33363973/article/details/78783481  竟然pip install csv 无果: 学习 ...

  6. Android-自己定义PopupWindow

    Android-自己定义PopupWindow 2014年5月12日 PopupWindow在应用中应该是随处可见的,非经常常使用到,比方在旧版本号的微信其中就用到下拉的PopupWindow.那是自 ...

  7. 一个简单的int型C++单链表的实现

    IntSLList.h //************************ intSLList.h ************************** // singly-linked list ...

  8. windows Server2012 之 IIS8.0配置安装完整教程

    IIS8.0是windows Server2012自带的服务器管理系统,和以往不同,IIS8.0安装和操作都比较简单,界面很简洁,安装也很迅速.今天我们重点完整的演示下Internet Informa ...

  9. vue - for 遍历对象和遍历对象数组

    1. 遍历对象时,参数: 第一个为值,第二个为键名,第三个为索引 <!DOCTYPE html> <html lang="en"> <head> ...

  10. Manual close is not allowed over a Spring managed SqlSession(转)

    最近用junit测试spring项目的时候,报错: Manual close is not allowed over a Spring managed SqlSession 意思是不允许手动关闭spr ...