装箱和拆箱 深度理解

提问:

首先我们来提两个疑问,我们自定义了一个类如Customclass类型,

Customclass myclass=new Customclass()

Object obj=myclass;

运行上面这段代码,我们会进行装箱操作吗?

基础知识:

.Net的类型分为两种,一种是值类型(Value Type ),另一种是引用类型(Reference Type)。这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上。那么如果要把一个值类型数据放到堆上,就需要装箱操作;反之,把一个放在堆上的值类型数据取出来,则需要进行拆箱操作。

说到具体程序代码上, 我们可以这样总结: 装箱是将值类型转换为引用类型 ;拆箱是在已装箱的前提下将引用类型转换为值类型.

我们要充分的了解装箱和拆箱,首先我们先得了解一下.net framework平台的类的构造.在这个平台上有一个万物之源,那就是System.Object类型,在之下系统又分了值类型(Value Type )和引用类型(Reference Type).值类型包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct),引用类型包括:类、数组、接口、委托、字符串等。所以到这里我们就可以得出一个结论,文章开头提的那个问题的答案也就不言而喻了.我们自定义声明的类型是一种引用类型,所以我们把他放到object里面的时候,是不会发生装箱操作的.

具体操作:

下面我们来解析一下装箱和拆箱系统做了那些操作

前面我们已经说到.值类型数据是分配在栈(stack)中,他是一个先进后出的结构,由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.而引用类型数据分配在堆(heap)上,其操作方式类似于数据结构中的栈。堆他是一种顺序随意的结构,一般由程序员分配释放若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。具体在.net框架上的情况你可以阅读  .NET中栈和堆的比较 这篇文章,这位博主翻译了四篇关于这方面的文章,为中国的IT视野做出了巨大的贡献啊.

我们来结合一个小例子说明一下装箱操作:

int i = 123; object o = (object)i;

对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。按三步进行。 
第一步:新分配堆内存(大小为值类型实例大小加上一个方法表指针和一个SyncBlockIndex)。 
第二步:将值类型的实例字段拷贝到新分配的内存中。 
第三步:返回堆中新分配对象的地址。这个地址就是一个指向对象的引用了。

我们通过这种方式将一个值类型的int i装箱为一个object类型的 o变量

拆箱就是一个逆过程了.将一个object 类型的o变量还原为int型的i变量,它进行了如下操作:

(1)环境须先判断堆栈上指向合法对象的地址,以及在对此对象向指定的类型进行转换时是否合法,如果不合法,就抛出异常;

(2)当判断类型转换正确,就返回一个指向对象内的值的指针。

针对上面的合法性判断,有两点需要我们注意:

(1)包含已装箱的值类型的引用的变量如果为null,就抛出一个NullReferenceException异常。

(2)如果引用指向的对象不是所要求的值类型的一个已装箱的实例,就抛出一个InvaildCastException异常

带来的影响:

我们可以从两个方面考虑:一个就是对于堆的操作效率比较低;另一个就是对于堆上分配的内存资源,需要GC来回收,从而降低程序效率。

显然,直观的来说.装箱时,生成的是全新的引用对象,这会有时间损耗,也就是造成效率降低。 
当然我们也可以直观的看出,拆箱所带来的性能损失是远小于装箱所带来的损失的.

OK.已经很晚了,明天再来发一篇文章主要介绍我们在编程中怎么解决装箱拆箱带来的性能损失.各位晚安.

时间: 2024-10-26 12:28:19

装箱和拆箱 深度理解的相关文章

[DotNet]深入理解C#的装箱和拆箱

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作.  1. 装箱在值类型向引用类型转换时发生 2. 拆箱在引用类型向值类型转换时发生 光上述两句话不难理解,但是往深处了解,就需要一些篇幅来解释了. 我们先看装箱时都会发生什么事情,下面是一行最简单的装箱代码 object obj = 1; 这行语句将整型常量1赋给object类型的变量obj: 众所周知常量1是值类型,值类型是要放在栈上的,而object是引用类型,它需要放在堆上:要把值类型放在堆上就需要执行一次装箱操作. 这行语句的IL代

全面理解java自动装箱和拆箱(转)

自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象.自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接. 如果你在Java1.5下进行过编程的话,你一定不会陌生这一点,你不能直接地向集合(Collections)中放入原始类型值,因为集合只接收对象.通常这种情况下你的做法是,将这些原始类型的值转换成对象,然后将这些转换的对象放入集合中.使用Integer,Double,Boolean等这些类我们可以将原始

C#中的装箱和拆箱的简单理解

1.代码: int i = 3; //装箱 object obj = i; //拆箱 int y = (int)obj; 2.过程: 装箱操作分为以下3个步骤: (1)内存分配:在托管堆中内存分配内存空间用来存放复制的实际数据 (2)完成实际数据的复制:将值类型实例的实际数据复制到新分配额内存中 (3)地址返回,将托管堆中的对象地址返回给引用类型变量 拆箱操作分为以下3个步骤: (1)检查实例:首先检查进行拆箱操作的引用类型是否为null,如果为null抛出异常,如果不为null则继续检查变量是

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

1.      装箱和拆箱是一个抽象的概念 2.      装箱是将值类型转换为引用类型 :拆箱是将引用类型转换为值类型       利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来 例如: int val = 100; object obj = val; Console.WriteLine (“对象的值 = {0}", obj); 这是一个装箱的过程,是将值类型转换为引用类型的过程 int val = 100; object obj =

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

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

6个重要的.NET概念栈,堆,值类型,引用类型,装箱,拆箱

介绍 这篇文章将解释6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.本文将会阐述当你声明一个变量时发生了什么并提前说明两个重要个概念:栈和堆.文章将围绕引用类型和值类型澄清一些重要基本信息.并通过一个简单的示例来演示装箱和拆箱引起的性能损失. 声明一个变量时发生了什么? 当你在.NET应用程序中声明了一个变量时,将会从RAM中分配一小块内存,在内存中存在三样东西:变量名称,数据类型和变量的值. 我们简单的说明下在内存中发生了什么,要知道变量在内存中的分配是取决于数据类型的.这里存在两种类型

[转]java 自动装箱与拆箱

转自:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2451996.html 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱): 其实按照我自己的理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象:例如用int来举例: //声明一个

装箱 Or 拆箱

1.引用.值类型 在.Net中所有的类型都是由基类System.Object继承过来的,比如我们最常用的int.string类型等,也就是经常说的所有的事物都是对象.而在上一篇中提到过,对象是存放在堆中的,因此所有的类型如果都放在堆中的话会造成效率低下. 为了解决这种效率低下的问题,因此才有了引用类型和值类型 值类型:Sbyte.Byte.Short.Ushort.Int.Uint.Long.Ulong.Char.Float.Double.Bool.Decimal).枚举(enum).结构(st