37. C# -- 装箱和拆箱

概念简述:

在装箱拆箱之前简单说一下值类型、引用类型:

值类型:原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)等,是在栈中分配内存,在申明的同时就初始化,以确保数据不为NULL;

引用类型:类、数组、接口、委托、字符串等,在堆中分配内存,初始化为null,引用型是需要GARBAGE COLLECTION来回收内存的,值型不用,超出了作用范围,系统就会自动释放;

装箱:将值类型转换为引用类型,用于在垃圾回收堆中存储值类型,是值类型到 object 类型或到此值类型所实现的任何接口类型的隐式转换;

拆箱:将引用类型转换为值类型,从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换;

利用装箱和拆箱功能,可通过允许值类型的任何值与Object类型的值相互转换,将值类型与引用类型链接起来

简例:

int val = 100;
object obj = val;
Console.WriteLine (“对象的值 = {0}", obj);
这是一个装箱的过程,是将值类型转换为引用类型的过程

int val = 100;
object obj = val;
int num = (int) obj;
Console.WriteLine ("num: {0}", num);
这是一个拆箱的过程,是将值类型转换为引用类型,再由引用类型转换为值类型的过程

(注: .NET中,数据类型划分为值类型和引用(不等同于C++的指针)类型,与此对应,内存分配被分成了两种方式,一为栈,二为堆(托管堆)。值类型只会在栈中分配,引用类型分配内存与托管堆,托管堆对应于垃圾回收。)

何时装箱

1、 调用一个含类型为Object的参数的方法,该Object可支持任意为型,当你需要将一个值类型(如Int32)传入时,则需要装箱;

2、 一个非泛型的容器,同样是为了保证通用,而将元素类型定义为Object。若要将值类型数据加入容器时,则需要装箱;

装箱拆箱效率

装箱:

1、 首先从托管堆中为新生成的引用对象分配内存;

2、 然后将值类型的数据拷贝到刚刚分配的内存中;

3、 返回托管堆中新分配对象的地址;

进行一次装箱要进行分配内存和拷贝数据这两项比较影响性能的操作。

拆箱:

1、 首先获取托管堆中属于值类型那部分字段的地址,这一步是严格意义上的拆箱;

2、 将引用对象中的值拷贝到位于线程堆栈上的值类型实例中;

严格意义上的拆箱,并不影响性能,但伴随这之后的拷贝数据的操作就会同boxing操作中一样影响性能。

理论上装箱时,生成的是全新的引用对象,这会有时间损耗,也就是造成效率降低。通过重载函数,也可以通过泛型来避免装箱。

对于装箱拆箱代码的优化,由于C#中对装箱和拆箱都是隐式的,所以,根本的方法是对代码进行分析,而分析最直接的方式是了解原理结何查看反编译的IL代码。比如:在循环体中可能存在多余的装箱,你可以简单采用提前装箱方式进行优化。

参考:

http://www.2cto.com/kf/201504/391285.html

时间: 2024-10-10 10:11:00

37. C# -- 装箱和拆箱的相关文章

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

1 //Java中的自动装箱和拆箱功能. 2 class AutoboxingUnboxing 3 { 4 public static void main(String[] args) 5 { 6 //直接把一个基本类型变量赋给Interger对象. 7 Integer inObj = 5; 8 Object inObj1 = 6; 9 //直接把一个boolean类型的变量赋给一个Object类型的变量. 10 Object boolObj = true; 11 //直接把Integer对象赋

List泛型集合、装箱和拆箱、Dictionary

1.List泛型集合 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _02_List泛型集合 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //创建泛型集合对象 14 //Li

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

阅读目录 一.什么是装箱?什么是拆箱?二.装箱和拆箱是如何实现的三.面试中相关的问题 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 回到顶部 一.什么是装箱?什么是拆箱? 我们知道 Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE5之前,如果要生成

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

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

【c#】装箱与拆箱

从内存执行的角度来看,值类型的内存分配在线程的堆栈上,而引用类型的内存分配在托管堆上.因此从值类型向引用类型的转换,势必牵涉到数据的拷贝与指针引用等操作. 装箱操作,大致过程为:在托管堆中分配新对象的内存,将值类型的字段拷贝到该内存中,然后返回该对象的地址,这样就完成了从值类型到引用类型的转变:拆箱操作,则是获取已装箱对象中来自值类型部分字段的地址.装箱与拆箱并非完全对称的互逆操作,拆箱并不包含字段的拷贝. 概念雷区: 装箱与拆箱不是完全对等的互逆操作.从内存的角度上看,拆箱的性能开销远小于装箱

Java中的装箱与拆箱

在J2SE5.0后推出了自动装箱和拆箱的功能,以提高我们的开发效率,然而自动装箱和拆箱实际上是通过编译器来支持的(并非语言本身,或者说虚拟机),因而这种支持也隐藏了部分内部实质,再加上某些类的优化(比如Integer里面的缓存等,参看关于缓存节),就更加容易在特定的环境下产生问题,并且如果不知道原来还无法调试.以下先是简单的介绍了编译器对装箱和拆箱的实现,并根据实现简单介绍一下可能会遇到的几个问题. 在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integ

值类型的装箱和拆箱

在CLR中为了将一个值类型转换成一个引用类型,要使用一个名为装箱的机制. 下面总结了对值类型的一个实例进行装箱操作时内部发生的事: 1)在托管堆中分配好内存.分配的内存量是值类型的各个字段需要的内存量加上托管堆上的所有对象都有的两个额外成员(类型对象指针和同步块索引)需要的内存量. 2)值类型的字段复制到新的分配的堆内存. 3)返回对象的地址.现在,这个地址是对一个对象的引用,值类型现在是一个引用类型. 拆箱不是直接将装箱过程倒过来.拆箱的代价比装箱低得多.拆箱其实就是一个获取一个指针的过程,该

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

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