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

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

  概念雷区:

  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. scrapy-splash抓取动态数据例子二

    一.介绍 本例子用scrapy-splash抓取一点资讯网站给定关键字抓取咨询信息. 给定关键字:打通:融合:电视 抓取信息内如下: 1.资讯标题 2.资讯链接 3.资讯时间 4.资讯来源 二.网站信 ...

  2. phpcms v9 wap手机门户站点内容页添加上一篇、下一篇的方法

    PHP源码修改:打开 phpcms\modules\wap\index.php 文件找到if(!$r || $r['status'] != 99) showmessage(L('info_does_n ...

  3. (转)Dubbo扩展点实现细节

    实现细节 (+) (#) 初始化过程细节 (+) (#) 解析服务 基于dubbo.jar内的META-INF/spring.handlers配置,Spring在遇到dubbo名称空间时,会回调Dub ...

  4. [ES6] 06. Arrow Function =>

    ES6 arrow function is somehow like CoffeeScirpt. CoffeeScript: //function call coffee = -> coffee ...

  5. 图片转为byte[]、String、图片之间的转换

    package com.horizon.action; import java.io.ByteArrayOutputStream; import java.io.File; import java.i ...

  6. rails执行sidekiq任务的时候报错“can't connect to local mysql server through socket '/var/run/mysqld/mysqld.sock'”

    rails执行sidekiq任务的时候报错“can't connect to local mysql server through socket '/var/run/mysqld/mysqld.soc ...

  7. hadoop权威指南(第四版)要点翻译(4)——Chapter 3. The HDFS(1-4)

    Filesystems that manage the storage across a network of machines are called distributed filesystems. ...

  8. Oracle中查询某字段不为空或者为空的SQL语句怎么写

    比如 insert into table a (a1,b1)values("a1",''); 对于这种情况,因为表里存的是'',其实是没有内容的,要查询这个字段,不能直接使用 se ...

  9. 如何为Drupal缓存对象指定缓存类?

    什么意思?意思是说,假如你有这样的需求,需要将cache_page缓存到数据库,其它的都缓存到memcache,这该怎么办? 看看_cache_get_object()的实现你就会知道上面的问题该怎么 ...

  10. java的日期格式使用

    转自:  关于java中六个时间类的使用和区别     java.util.Date java.sql.Date  java.sql.Time  java.sql.Timestamp java.tex ...