学习.NET的过程中,发现大多数的书都讲到了装箱(boxing)和拆箱(unboxing)的概念,至于为什么要理解装箱和拆箱?则总是一句话带过:优化程序的性能云云。至于为什么会对程序的性能产生影响,如何影响,我总感觉讲得并不透彻,当然也可能是我理解力有限。 这篇笔记,我并不打算对装箱和拆箱做全面的介绍,这些内容书上都有,csdn上也有很好的文章(请见kenli写的dotnet学习笔记一 - 装箱拆箱 http://www.csdn.net/Develop/Read_Article.asp?Id=19575),我只做简单的总结,并在此基础上引入两个例子,一个例子用ILDASM.EXE查看装箱和拆箱的过程,另外一个例子我编制一个简单例子分析正确理解装箱和拆箱对程序性能的影响。 由于在下面的例子和以后的例子我们将再次用到ILDASM,但不再给出详细的解释,因此给出MSDN关于反汇编语言的帮助信息,要查找汇编语言的命令,请在MSDN中.NET Framework/参考/类库/ System.Reflection.Emit 命名空间/OpCodes类中可以找到相关信息。总结1:.NET中所有类型都是对象,所有类型的根是System.Object。 总结2:类型分为值类型(value)和引用类型(regerence type)。C#中定义的值类型包括:原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)。引用类型包括:类、数组、接口、委托、字符串等。 实例一:读下列程序,你能说出其中进行了几次装箱和拆箱的操作吗? using System; class sample1 { public static void Main() { int i=10; object obj=i; Console.WriteLine(i+","+(int)obj); } } 其中发生了三次装箱操作和一次拆箱操作。第一次object obj=i;将i装箱;而Console.WriteLine方法用的参数是String对象,因此,i+","+(int)obj中,i需要进行一次装箱(转换成String对象),(int)obj将obj对象拆箱成值类型,而根据WriteLine方法,比较将(int)obj值装箱成引用类型。说起来这么复杂,大家看看ildasm.exe的反汇编结果(如下图),就很容易理解了。 注意图中红色圆圈的标识。 如果我们将Console.WriteLine(i+","+(int)obj); 改为: Console.WriteLine(obj+","+obj); 得到同样的效果,而其中仅进行一次装箱操作(object obj=i;),虽然这个程序并没有实际的意义,但是加深我们对概念的理解。 实例二:我这里我列出两个例子,装箱和拆箱对程序性能的影响不问自知。我的机器配置是P4 1.6A,512M内存。随后会列出测试的截图,你比我更快吗?当然是的?那么告诉我吧。:( // 例子1:boxing1.cs using System; using System.Collections; namespace test1 { class Class1 { static void Main(string[] args) { int count; DateTime startTime = DateTime.Now; ArrayList myArrayList = new ArrayList(); // 重复5次测试 for(int i = 5; i > 0; i--) { myArrayList.Clear(); // 将值类型加入myArrayList数组 for(count = 0; count < 5000000; count++) myArrayList.Add(count); //装箱 // 重新得到值 int j; for(count = 0; count < 5000000; count++) j = (int) myArrayList[count]; //拆箱 } // 打印结果 DateTime endTime = DateTime.Now; Console.WriteLine("Start: {0}\nEnd: {1}\nSpend: {2}", startTime, endTime, endTime-startTime); Console.WriteLine("Push ENTER to return commandline..."); Console.ReadLine(); } } } 下图是boxing1.exe的测试结果: // 例子2:boxing2.cs using System; using System.Collections; namespace test2 { class Class2 { static void Main(string[] args) { int count; ArrayList myArrayList = new ArrayList(); // 构造 5000000 字符串数组 string [] strList = new string[5000000]; for(count = 0; count < 5000000; count++) strList[count] = count.ToString(); // 重复5次测试 DateTime startTime = DateTime.Now; for(int i = 5; i > 0; i--) { myArrayList.Clear(); // 将值类型加入myArrayList数组 for(count = 0; count < 5000000; count++) myArrayList.Add(strList[count]); // 重新得到值 string s; for(count = 0; count < 5000000; count++) s = (string) myArrayList[count]; } // 打印结果 DateTime endTime = DateTime.Now; Console.WriteLine("Start: {0}\nEnd: {1}\nSpend: {2}", startTime, endTime, endTime-startTime); Console.WriteLine("Push ENTER to return commandline..."); Console.ReadLine(); } } } 下图是boxing2.exe的测试结果: 实例二说明:boxing1.cs的循环中包含一次装箱和一次拆箱(这里我均
浙公网安备 33010602011771号