我们先来看一个示例代码:

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ArrayList a = new ArrayList(); Point p; for (int i = ; i < ; i++)
{
p.x = p.y = i; a.Add(p);
} Console.ReadKey();
}
} struct Point
{
public Int32 x, y;
}
}

在本例中,ArrayList的Add方法原型如下:

public virtual Int32 Add(object value);

可以看来,Add方法需要获取一个Object类型参数,换言之,Add需要获取对托管堆上的一个对象的引用来作为参数。但在之前的代码中,传递的是值类型的参数。为了使代码能够工作,Point值类型必须转换成一个真正的、在堆中托管的对象。而且必须获取对这个对象的一个引用。

为了将一个值类型转换成一个引用类型,要使用一个名为"装箱"的机制。下面总结了对值类型的一个实例进行装箱时在内部发生的事情。

1)在托管堆中分配好内存。分配的内存量是值类型的各个字段所需要的内存量再加上托管堆的所有对象都有的两个额外成员需要的内存量。

2)值类型的字段复制到新分配的堆内存。

3)返回对象的地址。

在知道装箱如何进行之后,接着谈谈拆箱。

Point p = (Point)a[0];

现在要获取ArrayList的元素0中包含的引用,并试图将其放到一个Point值类型的实例p中。为了做到这一点,包含在已装箱Point对象中的所有字段都必须复制到值类型变量p中,后者在线程栈上。CLR分两步完成这个复制操作。第一步是获取已装箱的Point对象中的各个Point字段的地址,这个过程称为拆箱。第二步是将这些字段包含的值复制到基于栈的值类型实例中。

 static void Main(string[] args)
{
Int32 x = 5; Object o = x; Int16 y = (Int16)o; //抛出一个InvalidCastException异常 Int16 y = (Int16)(Int32)o; //这个是正确的写法 Console.ReadKey();
}

从逻辑上讲,完全可以获取o所引用的一个已装箱的Int32,然后将其强制转换为一个Int16。然而,在对一个对象进行拆箱的时候,只能将其转型为原先未装箱时的值类型。 

由于未装箱的值类型没有同步块索引,所以不能使用System.Threading.Monitor类型的各种方法(或者使用C#的lock语句)让多个线程同步对这个实例的访问。

虽然未装箱的值类型没有类型对象指针,但仍可调用由类型继承或重写的虚方法(比如Equals、GetHashCode或者ToString)。用于调用虚方法的值类型不会被装箱。然而,如果你重写的虚方法要调用方法在基类中的实现,那么在调用基类的实现时,值类型实例就会装箱。然而,调用一个非虚的、继承的方法时(比如GetType或MemberwiseClone),无论如何都要对值类型进行装箱。这是因为这些方法是由System.Object定义的,所以这些方法期望this实参指向堆上一个对象的指针。除以之外,将值类型的一个未装箱实例转型为类型的某个接口时,要求对实例进行装箱。这是因为接口变量必须包含对堆上的一个对象的引用。

[CLR via C#]值类型的装箱和拆箱的更多相关文章

  1. [CLR via C#]5.3 值类型的装箱和拆箱

    原文:[CLR via C#]5.3 值类型的装箱和拆箱 在CLR中为了将一个值类型转换成一个引用类型,要使用一个名为装箱的机制. 下面总结了对值类型的一个实例进行装箱操作时内部发生的事: 1)在托管 ...

  2. 【.Net基础二】浅谈引用类型、值类型和装箱、拆箱

    目前在看CLR via C#,把总结的记下来,索性就把他写成一个系列吧. 1.[.Net基础一] 类型.对象.线程栈.托管堆运行时的相互关系 2.[.Net基础二]浅谈引用类型.值类型和装箱.拆箱 引 ...

  3. CLR via 笔记 5.3 值类型的装箱和拆箱

    1.装箱 为了将一个值类型转换成一个引用类型,要使用一个名为装箱(Boxing)的机制. 1.在托管堆中分配好内存.分配的内存量是值类型的各个字段需要的内存量加上托管堆的所有对象都有的两个额外成员(类 ...

  4. 【深入理解CLR】2:细谈值类型的装箱和拆箱

    装箱 总所周知,值类型是比引用类型更“轻型”的一种类型,因为它们不作为对象在托管堆中分配,不会被垃圾回收,也不通过指针来引用.但在许多情况下,都需要获取对值类型的一个实例的引用.例如,假定要创建一个A ...

  5. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_值类型的装箱和拆箱(二)

    [注意]:如果知道自己写的代码会造成编译器反复对一个值类型进行装箱,请改成用手动方式对值类型进行装箱. [好处]:代码会变得更小.更快. [例子]: using System; public seal ...

  6. [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱

    在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...

  7. 浅谈.NET中的类型和装箱、拆箱原理

    谈到装箱拆箱,大概的意思就是值类型和引用类型的相互转换呗---值类型到引用类型叫装箱,反之则叫拆箱.这当然没有问题,可是你只知道这么多,那么建议你花点时间看看楼主这篇文章 1. .NET中的类型 为了 ...

  8. 从CLR角度来看值类型与引用类型

    前言 本文中大部分示例代码来自于<CLR via C# Edition3>,并在此之上加以总结和简化,文中只是重点介绍几个比较有共性的问题,对一些细节不会做过深入的讲解. 前几天一直忙着翻 ...

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

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

随机推荐

  1. python中的rabbitmq

    介绍 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议.MQ全称为Message Queue, 消息队列(MQ)是一种应用 ...

  2. QOS-交换机拥塞管理

    QOS-交换机拥塞管理 2018年7月7日 20:29 优先级映射: 根据信任的优先级,查找映射表,标记丢弃优先级和本地优先级 如果信任端口优先级,不同产品优先级标记方式可能不同,S3610处理过程如 ...

  3. 4-c++教程起航篇-学习笔记

    c++教程起航篇 我们会讲C++那些事,C++与C语言的关系. C++诞生于贝尔实验室. C++之父: 本贾尼·斯特劳斯特卢普 C++社区排行榜 最新排行,c++排名第三,Python排名第四 C++ ...

  4. mysql数据库目录存放位置更改

    http://haowen.blog.51cto.com/3486731/1274721 mysql数据库存储路径更改 使用了VPS一段时间之后发现磁盘空间快满了.本人的VPS在购买的时候买了500g ...

  5. yield学习

    如果要控制内存占用,最好不要用list来保存中间结果,而是通过iterable对象(range, xrange, generator等)来迭代.   yield 使函数变为generator,返回对象 ...

  6. Python学习笔记(一)一一一环境安装错误总结

    第三方库安装 1   windows存在多个版本的python,pip安装Python库失败 解决方案:进入对应官网下载安装包,步骤:1 下载安装包到C:\Python36\Lib\site-pack ...

  7. Linux命令应用大词典-第6章 文件处理

    6.1 sort:对文件中的数据进行排序 6.2 uniq:将重复行从输出文件中删除 6.3 cut:从文件每行中输出选定的字节.字符或字段 6.4 comm:逐行比较两个已经排序的文件 6.5 di ...

  8. javaee开发工具及环境配置过程

    在配置javaee开发环境的过程中遇到过很多问题,在此系统的整理一下我之前的配置过程 注:配置过程学习自<JSP&Servlet学习笔记(第二版)>详细过程可以阅读此书.在文章的最 ...

  9. spark操作数据库的几种方法

    一.使用jdbcRDD的接口: SparkConf conf = new SparkConf(); conf.setAppName("Simple Application").se ...

  10. ionic ios样式偏移解决方案。

    在css属性内增加: .item-ios [item-end] { //解决ios系统上尾部图标出现重影而增加的格式. margin: 0px -15.3px 0px 0px; margin-bott ...