看来,装箱和拆箱也不过如此,费了半天劲,刚把‘值’给装到‘箱’里去了,有费了更多的劲把它拆解了,郁闷啊!细心的观者,可能还能结合代码和MSIL看出,怎么在调用Console.WriteLine()的过程中又出现了两次box,是的,我本想偷懒逃过这节,但是既然已被发现,就应该大胆的面对,其实这就是传说中的“暗箱操作”啊! 因为Console.WriteLine方法有许多的重载版本,此处的版本是以两个String对象为参数,而具有object 类型的参数的重载是编译器找到的最接近的版本,所以,编译器为了求得与这个方法的原型一致,就必须对值类型的dubBox和dubUnBox分别进行装箱(转换成引用类型)。
所以,为了避免由于无谓的隐式装箱所造成的性能损失,在执行这些多类型重载方法之前,最好先对值进行装箱。现在我们把上述地代码改进为:
using System;
namespace StructApp { /// /// BoxAndUnBox 的摘要说明。 /// public class BoxAndUnBox { public BoxAndUnBox() { // // TODO: 在此处添加构造函数逻辑 // } /////////////////////////////////////////////////////////////////// static void Main(string[] args) { double dubBox = 77.77; object objBox = dubBox; double dubUnBox = (double)objBox; object objUnBox = dubUnBox; Console.WriteLine("The Value is '{0}' and The UnBoxed is {1}",objBox,objUnBox); } /////////////////////////////////////////////////////////////////// } } | MSIL代码:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 45 (0x2d) .maxstack 3 .locals init ([0] float64 dubBox, [1] object objBox, [2] float64 dubUnBox, [3] object objUnBox) 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: ldloc.2 IL_001a: box [mscorlib]System.Double IL_001f: stloc.3 IL_0020: ldstr "The Value is '{0}' and The UnBoxed is {1}" IL_0025: ldloc.1 IL_0026: ldloc.3 IL_0027: call void [mscorlib]System.Console::WriteLine(string, object, object) IL_002c: ret } // end of method BoxAndUnBox::Main | 我晕!这算嘛事儿呀!看完后是不是该吐血的吐血,该上吊的上吊呀!相信能坚持到看完最后一个 "!" 的同志一定是个好同志。
其实,我们也可以妄加揣测一下:引用型应当属于高级类型,而值型属于原始类型,箱只是一个概念、一个秩序、一套规则或准确说是一个逻辑。原始的东西作为基础,其复杂性和逻辑性不会很高,而高级的东西就不那么稳定了,它会不断的进化和发展,因为这个逻辑的‘箱’会不断地被要求扩充和完善。由此思路推演,我们就不难预测出未来我们需要努力的方向和成功机会可能存在的地方—— !
|
|