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

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. sublime解决gbk中文乱码包括Package Control: Install Package 无法使用

    最近喜欢上了sublime,打算抛弃notepad,但是发现sublime居然不支持gbk编码,再上网查找资料之后,总结了一套解决方法,目前为止是行之有效的. 日期:2019年3月14日 第一步:到G ...

  2. BZOJ1011 莫比乌斯反演(基础题

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1101 [题目大意] 求[1,n][1,m]内gcd=k的情况 [题解] 考虑求[1,n ...

  3. Java8 Lambda表达式实战之方法引用(一)

    方法的引用 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用 方法 ...

  4. php7+apache2.4+mysql 环境配置(window环境)

    最近,小主从事PHP开发.特将最近如何搭建php7的过程记录在此!希望有需要,可以借鉴!( 电脑必须win7 sp1以上, .netframework4 ) Windows7安装php7,Win7+p ...

  5. Redis系列化方式有哪些?哪个系列化性能最好?

    Redis系列化方式有JDK系列化.JSON系列化.XML系列化等多种.我专门测试过,在我的笔记本电脑上保存5万条User对象到Redis,JDK系列化方式平均要15秒,JSON系列化方式只要13秒多 ...

  6. Nginx初体验(一):nginx介绍

    今天我们来介绍一下Nginx. Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件(IMAP/POP3)代理服务器 特点: 反向代理,负载均衡,动静分离 首先我们来介绍一下正向代理服务器 ...

  7. 【原创】Odoo开发文档学习之:构建接口扩展(Building Interface Extensions)(边Google翻译边学习)

    构建接口扩展(Building Interface Extensions) 本指南是关于为Odoo的web客户创建模块. 要创建有Odoo的网站,请参见建立网站;要添加业务功能或扩展Odoo的现有业务 ...

  8. 成都Uber优步司机奖励政策(2月17日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. linux下免安装版本mysql5.5 配置

    进入/usr/local #cd /usr/local 下载 #wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.39-linux ...

  10. UPA深度性能报告解读

    WeTest 导读 UPA作为腾讯WeTest与Unity官方联合打造的客户端性能分析工具,为开发者提供了极大的便利和效能提升.产出的分析报告内容详尽,但您是否真的读懂了报告?是否了解每项数据的含义? ...