`
starnc
  • 浏览: 145172 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

C#装箱与拆箱

    博客分类:
  • .NET
阅读更多

要掌握装箱与拆箱,就必须了解CTS及它的特点。

NET重要技术和基础之一的CTS(Common Type System)。顾名思义,CTS就是为了实现在应用程序声明和使用这些类型时必须遵循的规则而存在的通用类型系统。.Net将整个系统的类型分成两大类 ——Value Type 和 Reference Type。。,多数的OO语言存在这个弱点,原因就是因为他们的原类型没有共同的基点,于是他们在本质上并不是真正的对象C++更依赖于对象,而非面向对象。.Net环境的CTS 给我们带来了方便。第一、CTS中的所有东西都是对象;第二、所有的对象都源自一个基类——System.Object类型。这就是所谓的单根层次结构(singly rooted hierarchy)关于System.Object的详细资料请参考微软的技术文档。CTS  Value Type的一个最大的特点是它们不能为null,Value Type的变量总有一个值。在传递Value Type的变量时,实际传递的是变量的值,而非底层对象的“引用”。CTS  Reference Type就好像是类型安全的指针,它可以为null。当值为null时,说明没有引用或类型指向某个对象。声明一个引用类型的变量时,被操作的是此变量的引用(地址),而不是数据。 

    使用这种多类型系统时如何有效的拓展和提高系统的性能?就是今天探讨的问题,西雅图人提出了Box and UnBox的想法。简言之,装箱就是将value type转换为reference type;反之,就是拆箱。

装箱过程:

第一步将一个值压入堆栈;

第二步将引用类型转换为值类型;

第三步间接将值压栈;第四步传值给dubUnBox。

代码如下:

using System;
namespace Box
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/////////////////////////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box1 =11.222; /// 定义一个值形变量
object objBox =box1; /// 将变量的值装箱到 一个引用型对象中
Console.WriteLine("The Value is '{0}' and The Boxed is {1}",box1,objBox.ToString());
}

}
}

打开ildasm.exe

MSIL代码如下:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
//
代码大小 42 (0x2a)
.maxstack 3
.locals init ([0] float64 box1,
              [1] object objBox)
IL_0000: nop

IL_0001: ldc.r8 11.222
IL_000a: stloc.0 //
第IL_0000至IL_000a是定义值型变量的
IL_000b: ldloc.0
IL_000c: box [mscorlib]System.Double
IL_0011: stloc.1     //
第IL_000b 至 IL_0011 行是描述object objBox =box1代码的
IL_0012: ldstr "The Value is '{0}' and The UnBoxed is {1}"
IL_0017: stloc.0
IL_0018: box [mscorlib]System.Double
IL_001d: stloc.1
IL_001e: callvirt instance string [mscorlib]System.Object::ToString()

IL_0023: call void [mscorlib]System.Console::WriteLine(string,
object,
object)

IL_0028: nop
IL_0029: ret
} // end of method BoxAndUnBox::Main

当box1被装箱时所发生的过程:

(1)划分堆栈内存,在堆栈上分配的内存 = box1的大小 + objBox及其结构所占用的空间;(2) box1的值(11.222)被复制到新近分配的堆栈中;

(3)将分配给objBox的地址压栈,此时它指向一个object类型,即引用类型。

拆箱过程:

装箱的逆过程。值得注意以下几点:box time不需要显式的类型转换,在unbox时就必须进行类型转换。因为引用类型的对象可以被转换为任何类型。电脑和人脑一个差别的体现就在于此!哈哈!类型转换不容回避的将会受到来自CTS管理中心的监控——其标准自然是依据规则。

下面这段代码:

using System;
namespace UnBox
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/////////////////////////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box2 = 11.222;
object objBox = box2;
double dubUnBox = (double)objBox; /// 将引用型对象拆箱 ,并返回值
Console.WriteLine("The Value is '{0}' and The UnBoxed is {1}",box2,dubUnBox);
}
/////////////////////////////////////////////////////////////////////////////////////
}
}

本段代码多加了一行double dubUnBox = (double)objBox;

这段代码的含义:

第一步将一个值压入堆栈;

第二步将引用类型转换为值类型;

第三步间接将值压栈;

第四步传值给dubUnBox。

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
//
代码大小 48 (0x30)
.maxstack 3
.locals init ([0] float64 box1,
[1] object objBox,
[2] float64 dubUnBox)
IL_0000: ldc.r8 77.769999999999996
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: box [mscorlib]System.Double
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: unbox [mscorlib]System.Double
IL_0017: ldind.r8
IL_0018: stloc.2
IL_0019: ldstr "The Value is '{0}' and The UnBoxed is {1}"
IL_001e: ldloc.0
IL_001f: box [mscorlib]System.Double
IL_0024: ldloc.2
IL_0025: box [mscorlib]System.Double
IL_002a: call void [mscorlib]System.Console::WriteLine(string,
object,
object)
IL_002f: ret
} // end of method BoxAndUnBox::Main

//

第IL_0011 至 IL_0018 行是描述double dubUnBox = (double)objBox代码的。

描述一下objBox在拆箱时的情况:(1)环境须先判断堆栈上指向合法对象的地址,以及在对此对象向指定的类型进行转换时是否合法,如果不合法,就抛出异常;(2)当判断类型转换正确,就返回一个指向对象内的值的指针。

改进:

为了避免由于无谓的隐式装箱所造成的性能损失,在执行这些多类型重载方法之前,最好先对值进行装箱。

代码改进:

using System;
namespace NewBU
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
///////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box1 = 11.222;
object objBox = box1;
double dubUnBox = (double)objBox;
object objUnBox = dubUnBox;
Console.WriteLine("The Value is '{0}' and The UnBoxed is {1}",objBox,objUnBox);
}
///////////////////////////////////////////////////////////////////
}
}  

 

转载自http://www.cnblogs.com/qunews/archive/2007/10/03/913349.html

分享到:
评论

相关推荐

    C#装箱与拆箱1

    C#装箱与拆箱第一部分。是一个很好的视频,帮助大家学习C#装箱和拆箱的知识

    装箱与拆箱(二)

    在C#编程语言中,装箱与拆箱是两种重要的操作,主要涉及到值类型与引用类型之间的转换。本文将深入探讨这两个概念,并结合实例来帮助理解。 首先,我们需要明确值类型(如int、bool、char、结构体等)和引用类型...

    C#装箱和拆箱2

    C#装箱和拆箱视频第二部分,可以结合第一部分的视频看。对初学者很有帮助

    装箱与拆箱(一)

    在C#编程语言中,装箱与拆箱是两种关键的操作,它们涉及到值类型与引用类型之间的转换。本文将深入探讨这两个概念,以及它们在实际编程中的应用。 首先,我们来理解什么是装箱。装箱(Boxing)是指将值类型(如int...

    C# 装箱和拆箱[整理].pdf

    【C# 装箱和拆箱】是C#编程中的关键概念,涉及到值类型与引用类型之间的转换。装箱是将值类型转换为引用类型,而拆箱则是将引用类型转换回值类型。这一机制使得C#能够处理不同类型之间的交互,尤其是在需要使用通用...

    C#语言中的装箱和拆箱操作

    C#语言中的装箱和拆箱操作 C#语言中的装箱和拆箱操作是类型系统中的核心概念,它们使得在C#类型系统中任何值类型、引用类型和object对象类型之间进行转换。装箱和拆箱机制可以将任何类型的值看作是object类型。 ...

    C# 装箱和拆箱的知识回顾

    C#中的装箱和拆箱是两种特殊类型的转换操作,它们涉及到值类型与引用类型之间的交互。在C#中,值类型包括基本类型(如int、char、bool等)和结构(如DateTime、Decimal等)。而引用类型主要是类实例以及接口实例。...

    深入理解C# 装箱和拆箱(整理篇)

    深入理解C#装箱和拆箱 概述: C#中的装箱(Boxing)和拆箱(Unboxing)是类型系统的核心概念,允许值类型和引用类型之间相互转换。装箱是将值类型转换为引用类型,而拆箱是将引用类型转换为值类型。 1. 装箱和拆箱...

    C#装箱与拆箱操作的深入讲解

    都知道C#有装箱和拆箱的操作,听闻也都是讲int类型转换成object类型就是装箱,将object类型再转回int类型就是拆箱。 描述的通俗点: 装箱 将值类型转换成引用类型, 拆箱 将引用类型转换成值类型。 那看来是要先...

    C#示例:装箱、拆箱、自定义数据类型转换、ToString方法重载、类方法扩展

    在C#编程中,装箱、拆箱、自定义数据类型转换、ToString方法重载以及类方法扩展是几个核心概念,对于理解和优化程序性能至关重要。本文将深入探讨这些主题,并通过具体的实例来阐述它们的应用。 1. 装箱与拆箱 装箱...

    c#装箱和拆箱知识整理

    利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来 例如: 代码如下:int val = 100; object obj = val; Console.WriteLine (“对象的值 = {0}”, obj); 这是...

    浅析C# 装箱和拆箱

    浅析C# 装箱和拆箱 C# 中的装箱和拆箱是两个重要的概念,它们之间的转换涉及到存储上的变化,影响性能,需要避免装箱和拆箱操作。 一、装箱 装箱是将值类型转换为引用类型的过程。例如,int 类型的变量 i 赋值给 ...

    C#源代码-装箱和拆箱.zip

    在.NET框架中,C#是一种面向对象的编程语言,它提供了装箱和拆箱的概念来处理值类型与引用类型之间的转换。本压缩包文件“C#源代码-装箱和拆箱.zip”显然包含了关于这一主题的源代码示例,这对于我们深入理解这两种...

    C#装箱和拆箱原理详解

    在C#编程语言中,装箱(Boxing)和拆箱(Unboxing)是两种重要的操作,它们涉及到值类型(Value Types)与引用类型(Reference Types)之间的转换。值类型包括基本数据类型如int、char、bool等,以及结构体(Struct...

    C#实现装箱与拆箱操作简单实例

    本文以一个简单实例讲述了C#装箱和拆箱操作的实现方法,简单来说装箱是将值类型转换为引用类型;拆箱是将引用类型转换为值类型,是涉及栈和堆的使用方面的东西,学过C#的人应该都知道,所以这里就不哆嗦了,本例代码...

    轻松学习C#的装箱与拆箱

    首先看一看什么是装箱和拆箱?  简单的来说:  装箱就是值类型转换为引用类型;  拆箱就是引用类型转换为值类型。  值类型,包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、...

    C#装箱和拆箱操作实例分析

    本文实例讲述了C#装箱和拆箱操作。分享给大家供大家参考,具体如下: 1. C#中的装箱 C#中的装箱就是把一个值类型隐式地转换为object类型,转换过程中采用的是值的拷贝而不是引用,这从下面的例子可以看出: using ...

Global site tag (gtag.js) - Google Analytics