日期:2014-05-17 浏览次数:20796 次
1.性能
性能是泛型的一个主要优点。
直接上例子,通过实例可以让我们很好的理解这一点。
Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //开始监视 //-----代码片段1------------------Start ArrayList al = new ArrayList(); for (int i = 1; i <= 10000000; i++) { al.Add(i); } foreach (int i in al) { //do what you want int j = i + 1; } //-----代码片段1------------------End stopwatch.Stop(); //停止监视 TimeSpan timespan = stopwatch.Elapsed; //获取代码运行时间 Console.WriteLine("代码片段1执行时间为:" + timespan.ToString()); Stopwatch stopwatch1 = new Stopwatch(); stopwatch1.Start(); //开始监视 //-----代码片段2------------------start List<int> il = new List<int>(); for (int i = 1; i <= 10000000; i++) { il.Add(i); } foreach (int i in il) { //do what you want int j = i + 1; } //-----代码片段2------------------end stopwatch1.Stop(); //停止监视 TimeSpan timespan1 = stopwatch1.Elapsed; //获取代码运行时间 Console.WriteLine("代码片段2执行时间为:" + timespan1.ToString());
代码运行结果为:
很显然,代码片段1的运行时间远远大于代码片段2 的运行时间。
下面将详细地说明一下代码片段1及代码片断2都干了些什么,以及是什么造成了两段代码运行时间的巨大差距。
首先,你应该能看出,代码片段1与代码片段2的功能完全等价,都是将1到10000000之间的整数循环添加进集合(ArrayList或List<T>),再从集合中循环取出这10000000个整数,做你想做的处理(想做就做呗,呵呵)。
既然功能一样,那么性能为什么会有如此之大的区别呢。
因为代码片段1中,ArrayList存储对象时,Add()方法被定义为接受一个对象(object)作为参数(见图* ArrayList Add()方法签名),所以使用Add()方法接受一个整型数据时,需要进行装箱操作。在读取ArrayList中的元素时,要进行拆箱,把对象转换成整型类型。
图* ArrayList Add()方法签名
可见,装箱与拆箱的实现并不难,但是性能损失较大。
当循环迭代次数很多时,性能损耗尤其明显。对于这一点,我们可以做个简单的实验,将实例的循环次数改为1000,得到以下结果:
结果显示:这种情况下,代码片段1的执行时间约为代码片段2执行时间的两倍。而循环次数为10000000时,代码片段1的执行时间约为代码片段2执行时间的四倍。
最后,将循环次数设置为1,此时运行结果为:
这种情况下,代码片段1的执行时间仍约为代码片段2执行时间的两倍(其实是<