提出问题
本文使用下面的实例来说明问题,以下是实例的完整代码。
//************************************************************ // // Sum应用示例代码 // // Author:三五月儿 // // Date:2014/09/10 // // http://blog.csdn.net/yl2isoft // //************************************************************ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace LinqSumExp { class Program { static void Main(string[] args) { Console.WriteLine("数据准备中,请稍后..."); List<Score> scoreList = CreateScoreList(); Console.WriteLine("正在执行中,请稍后..."); Stopwatch sw1 = new Stopwatch(); sw1.Start(); //------------代码片段1--------------------start int mathScoreSum1 = 0; int chineseScoreSum1 = 0; int engLishScoreSum1 = 0; int physicsScoreSum1 = 0; int chemistryScoreSum1 = 0; int biologyScoreSum1 = 0; foreach (var s in scoreList) { mathScoreSum1 += s.MathScore; chineseScoreSum1 += s.ChineseScore; engLishScoreSum1 += s.EngLishScore; physicsScoreSum1 += s.PhysicsScore; chemistryScoreSum1 += s.ChemistryScore; biologyScoreSum1 += s.BiologyScore; } //------------代码片段1--------------------end sw1.Stop(); TimeSpan ts1 = sw1.Elapsed; Console.WriteLine("代码片段1的执行时间为:" + ts1.TotalMilliseconds); Stopwatch sw2 = new Stopwatch(); sw2.Start(); //------------代码片段2--------------------start int mathScoreSum2 = 0; int chineseScoreSum2 = 0; int engLishScoreSum2 = 0; int physicsScoreSum2 = 0; int chemistryScoreSum2 = 0; int biologyScoreSum2 = 0; mathScoreSum2 = scoreList.Sum(it => it.MathScore); chineseScoreSum2 = scoreList.Sum(it => it.ChineseScore); engLishScoreSum2 = scoreList.Sum(it => it.EngLishScore); physicsScoreSum2 = scoreList.Sum(it => it.PhysicsScore); chemistryScoreSum2 = scoreList.Sum(it => it.ChemistryScore); biologyScoreSum2 = scoreList.Sum(it => it.BiologyScore); //------------代码片段2--------------------end sw2.Stop(); TimeSpan ts2 = sw2.Elapsed; Console.WriteLine("代码片段2的执行时间为:" + ts2.TotalMilliseconds); } static List<Score> CreateScoreList() { List<Score> scoreList = new List<Score>(); Random rd = new Random(); for (int i = 0; i < 100; i++) { Score s = new Score(); s.StudentId = i; s.StudentName = "s" + i.ToString(); s.MathScore = rd.Next(0, 100); s.ChineseScore = rd.Next(0, 100); s.EngLishScore = rd.Next(0, 100); s.PhysicsScore = rd.Next(0, 100); s.ChemistryScore = rd.Next(0, 100); s.BiologyScore = rd.Next(0, 100); scoreList.Add(s); } return scoreList; } } public class Score { public int StudentId { get; set; } public string StudentName { get; set; } public int MathScore { get; set; } public int ChineseScore { get; set; } public int EngLishScore { get; set; } public int PhysicsScore { get; set; } public int ChemistryScore { get; set; } public int BiologyScore { get; set; } } }实例中先定义Score类,使用Score类来保存学生各门功课的成绩,其中属性MathScore、ChineseScore、EngLishScore、PhysicsScore、ChemistryScore、BiologyScore分别用来保存数学、语文、英语、物理、化学、生物的成绩。接着,在CreateScoreList方法中生成包含100个Score对象的集合。最后,使用代码片段1和代码片段2来计算集合中各门功课的总和,其中,代码片段1通过遍历集合的方法来求和,而代码片段2使用Linq的求和方法Sum来实现求和。很显然,两种方法都可以完成求和这个基本功能。但是,在实际开发中,很多时候除了实现基本功能外,还需要考虑其他许多东西,比如性能。那么,这里我就弱弱的问一句:那种方法性能更好?
答案揭晓
大家请看黑板。(呵呵,是不是好黑好黑的一块板子啊)
图1 程序运行结果图
从程序的执行结果来看,方法1的性能更好。
你可能会说,仅仅通过一次结果无法得出这个结论,因为偶然性。
为了让你心服口服,那我就继续执行,执行,再执行。
经过我n多次重复试验(n到底有多大,你猜),发现:每一次都是方法1耗时更少,方法1性能好于方法2。
为了让我们的实验更具有说服力,增加数据量为1000,10000,100000来执行程序,下面是实验结果:
还是方法1耗时更少吧?
你要是还不服,那我也没办法了,反正我是相信这个结果了。
那么为什么会有这个结果呢?
原因说明
查看Linq求和方法Sum的源码,代码如下所示:
public static int Sum(this IEnumerable<int> source) { if (source == null) { throw Error.ArgumentNull("source"); } int num = 0; foreach (int num2 in source) { num += num2; } return num; }
很显然,每调用一次Linq的求和方法都会遍历一次集合,所以,方法2会遍历集合5次,而方法1只需遍历集合1次,这就是原因所在。
当然,需要求和的字段越多,数据量越大,两种方法的性能差距将越大。其实,除了在使用Linq的求和方法Sum时会遇见这个问题外,在使用Linq中其他扩展方法时也会遇到这种问题,希望大家以后注意了。
使用Linq求和方法Sum计算集合中多个元素和时应该注意的性能问题
原文地址:http://blog.csdn.net/yl2isoft/article/details/39188641