A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张林杰 中级黑马   /  2013-10-11 12:29  /  1746 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张林杰 于 2013-10-14 21:04 编辑

问题一:在MSDN中,装箱的定义是:装箱是将值类型转换为 object 类型或由此值类型实现的任一接口类型的过程。
             链接:http://msdn.microsoft.com/zh-cn/library/vstudio/yz2be5wk.aspx
             按我的理解,装箱的定义是:装箱就是值类型转换为引用类型的过程,并且两种类型存在继承关系(我这样理解对吗?)。
             所以问题为:下面的式子有没有发生装箱、拆箱?
  1. //问题1.1
  2. int a=1;
  3. ValueType vt=a;//值类型隐式继承自System.ValueType 类型,该类型为引用类型
  4. int b=(int)vt;
复制代码
问题二:装箱会在堆中新开内存,而且拆箱的强制转换很消耗时间,所以避免装拆箱,最好是函数的重载以及使用泛型,
             就如Console.WriteLine()方法。此部分问题来源于:
             http://www.cnblogs.com/wenjiang/archive/2013/03/14/2959466.html 这篇文章值得一读
             问题是:以下式子会发生装拆箱吗?
  1. //问题2.1
  2. int n=1;
  3. Console.WriteLine(n);
复制代码
  1. //问题2.2
  2. int m=1;
  3. Console.WriteLine("{0}",m);
复制代码
  1. //问题2.3
  2. int number = 5;
  3. Object obj = number;
  4. number = 10;
  5. Console.WriteLine(number + "," + (int)obj);//原文中的解释没看懂...
复制代码
  1. //问题2.4
  2. int a=1;
  3. string b=a.ToString();//a重写了基类ValueType的Tostring()方法?那此处发生装箱吗...
复制代码
暂时就这样,欢迎大家解答~





评分

参与人数 1技术分 +2 收起 理由
haxyek + 2

查看全部评分

12 个回复

倒序浏览
我所知道的:
装箱和拆箱使值类型能够被视为对象,对值类型装箱将把该值类型打包到Object引用类型的一个实例中。
问题2.3正好就是一个装箱和取消装箱的操作
  • int number = 5;
  • Object obj = number; //装箱
  • number = 10;
  • Console.WriteLine(number + "," + (int)obj);//取消装箱

评分

参与人数 1技术分 +1 收起 理由
haxyek + 1

查看全部评分

回复 使用道具 举报
本帖最后由 面朝大海,春暖 于 2013-10-11 15:16 编辑

问题一:不会,既然装箱的定义是:装箱是将值类型转换为 object 类型,object是所有类的基类,因此包括System.ValueType ,那么ValueType 定义的类型不一定是object类型,与定义不符,所以不会发生装箱、拆箱。
问题二:
只有2.3发生了装箱、拆箱。。取消装箱即拆箱,正常的拆箱:int num=(int)obj;2.3中只是没赋给新的变量而已。。

评分

参与人数 1技术分 +1 收起 理由
haxyek + 1

查看全部评分

回复 使用道具 举报
本帖最后由 夏闯富 于 2013-10-12 11:32 编辑
  1. int i=123;
  2. object o=i;//隐示装箱
  3. object ol=(object)i;//显示装箱

  4. o=123;
  5. i=(int)o;//拆箱
复制代码
问题二不属于拆箱,那些只是调用的不同的WriteLine()的重载方法,变量没有做任何类型转换。

WriteLine()的重载.png (66.11 KB, 下载次数: 54)

WriteLine()全部重载

WriteLine()全部重载

评分

参与人数 1技术分 +1 收起 理由
haxyek + 1

查看全部评分

回复 使用道具 举报
先感谢楼上各位的回答,不过我还是认为问题一中应该是发生装箱了的,加入没有装箱,一个值类型怎么可以赋值给一个引用类型呢:  ValueType(引用类型) vt=a(值类型)(两者继承关系); 就像不能把int类型直接赋值给string,如int a=1;string b=a;(int和string无继承关系),既然可以复制,说明就发生了装箱
回复 使用道具 举报
夏闯富 发表于 2013-10-12 11:23
问题二不属于拆箱,那些只是调用的不同的WriteLine()的重载方法,变量没有做任何类型转换。
...

那比如问题2.2中int m=1;Console.WriteLine("{0}",m);
这个应该是调用public static void WriteLine(string format,object arg0);这个重载方法,那就是m(值类型)复制给arg0(object类型-就是引用类型),则发生了装箱
回复 使用道具 举报
本帖最后由 夏闯富 于 2013-10-12 19:54 编辑
张林杰 发表于 2013-10-12 16:10
那比如问题2.2中int m=1;Console.WriteLine("{0}",m);
这个应该是调用public static void WriteLine(stri ...


嗯,你说的 对,我重新看了一下:
问题2.1 没有发生装拆箱
问题2.2 发生了装箱
问题2.3 任何类型+"字符串"=字符串(String类型),相当于“任何类型”调用了ToString()方法(number.ToString()没有装箱操作,但(int)obj这一过程有拆箱操作)
问题2.4 不再仅是内存级别的转换,而是考虑数据意义的转换。它是一个加工、改造的过程。(有些有拆装箱,有些无拆装箱;此处是int强制转换到string,无拆装箱)
回复 使用道具 举报
额,再顶一下。。
回复 使用道具 举报
我也再帮你顶一个
回复 使用道具 举报
装箱(boxing,box)        将值类型赋值给引用类型, object o = 12;
拆箱(unboxing)        就是将装箱的值类型强转为对应的数据, int n = (int)o;

我是运行程序,用reflector编译器看拆箱和装箱的
更多图片 小图 大图
组图打开中,请稍候......
回复 使用道具 举报
ˋ初°见 发表于 2013-10-14 20:17
装箱(boxing,box)        将值类型赋值给引用类型, object o = 12;
拆箱(unboxing)        就是将装箱的值类型强转为对 ...

非常感谢:handshake
我明白了!
回复 使用道具 举报
张林杰 发表于 2013-10-14 20:41
非常感谢
我明白了!

:loveliness:
回复 使用道具 举报
问题总结:
通过IL代码分析如下,
问题1.1 发生了装拆箱,值类型到引用类型,并且存在继承关系
问题2.1 没有发生任何装拆箱,因为Console.WriteLine()方法进行了重载
问题2.2 发生了装箱,调用了public static void WriteLine(string format,object arg0);
问题2.3 发生了三次装箱,一次拆箱,因为Console.WriteLine(number + "," + (int)obj);最终调用了string.Contact()
问题2.4 没有发生任何装拆箱,int类型进行基类ToString方法的重写,并没有转换为基类
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马