[C# Tips]再谈值类型的装箱和拆箱

Freesc Huang @ HUST All Rights Reserved
2008-2-11

Keywords
.NET Framework,C#,值类型,装箱,拆箱,CLR

正文
半年之前,我曾经写过一篇关于值类型装箱问题的短文(这里),现在看来,有些东西当时还是没有完全说开,这次特地拿了一个例子再来谈谈。理解这些问题,对于一个.NET程序员来说很基础,也很重要,对我们理解CLR和编写高效的程序都是很有帮助的。至于什么是值类型,什么是装箱拆箱(box&unbox),在此不做赘述,先来看看下面短短的几行代码:

Code

程序很短很简单,定义了一张火车票(Ticket)的结构,它只包括起点,终点和里程,它是值类型(结构派生自System.ValueType)。而我们主要关注的是围绕这张火车票的几个输出。

首先,创建了一个火车票的实例t(第38行), 初始化为北京到汉口,1225公里,接着第一次调用Console.WriteLine,因为Console.WriteLine() 没有参数为Ticket的重载,这里会对t进行装箱(就像这里提到的一样),而这个“已装箱”的票(姑且称作tII)会被CLR默认为是个Object,然后在这个Object实例tII上调用ToString(),而此时CLR在这个已装箱的Ticket的方法表中发现这个类型重写了ToString()方法,它会隐式的调用这个方法让我们顺利的得到显示"From 北京 To 汉口,1225 km"。也许我注释掉的那句代码会让您更好的理解这个过程。

随后,还是在那个值类型的t(而非tII)上调用Rebook,改成去上海,1400公里。然后再调用WriteLine,经过与前面相同的过程,我们如愿得到了输出"From 北京 To 上海,1400 km"。

接着,我们显式地将t装箱,其实这两行代码(第48,49行)跟第43行注释掉的代码是一样的,WriteLine()方法本身就有一个参数为Object的重载。于是我们仍能如愿得到"From 北京 To 上海,1400 km"。

接下来这一句比较有趣了,我们将o指向的tII拆箱,将相应的字段复制到堆栈上一个值类型实例tIII中,然后再对tIII调用Rebook方法,将其改为从北京到广州,注意,这里的修改是在堆栈上直接进行的。与托管堆上的o没有任何关系,于是此时调用ConsoleWriteLine(o);输出仍然为"From 北京 To 上海,1400 km"。

为了不让tIII成为游离于我们控制之外的垃圾,我们让Rebook立刻返回给我们这个tIII,并复制给一个叫t2的实例,并输出,这样我们才得到了修改过的最终结果"From 北京 To 广州,2000 km"。
程序输出如下:


程序代码在这里
本文算作是对之前那篇随笔的补充和扩展,也希望通过这个例子能让大家更加明白值类型装箱拆箱的原理和CLR在这背后的 行为,达人们轻点拍。欢迎大家多交流:-)


 

posted on 2008-02-11 20:51 Freesc Huang 阅读(412) 评论(2) 编辑 收藏

评论

#1楼 2008-02-12 19:06 Chris.Wang[未注册用户]

不错,过程说得比较详细,转走了 呵呵  回复 引用   

#2楼[楼主] 2008-02-12 20:45 fox23      

@Chris.Wang

:-) 多多交流
 回复 引用 查看   

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

公告

These postings are provided "AS IS" with no warranties
and confer no rights.


Locations of visitors to this page

Blog Keywords
Embedded System,Visual Studio,.Net Framework,.Net Compact Framework,.Net Micro Framework,Windows Mobile,Windows Embedded CE,Emulator,WCF,CLR,Design & Pattern,C/C++,C#,Matlab,Algorithms
昵称:Freesc Huang
园龄:4年11个月
粉丝:32
关注:4

统计

  • 随笔 - 197
  • 文章 - 0
  • 评论 - 840

搜索

 

随笔分类(227)

随笔档案(197)

Blogs

Link

积分与排名

最新评论

阅读排行榜

评论排行榜

推荐排行榜