If you search is Linq faster the Foreach the answer always is no a foreach is. I also found another stackoverflow question where the question asker had not done a "warmup" so I've included a "warmup" in my code.
My code example for some reason did not act as I expected. I'm thinking what I've done is make the no linq path loop twice--once the first time and once at the sum. Where as the linq example loops only once at the end when it does a sum. What do you think? Is my test flawed or is this a scenario where linq actually buys us a good performance increase?
public class NumberObject { public Int32 Number { get; set; } }
public IEnumerable<NumberObject> GetNumbersWithoutLambda()
{
IEnumerable<Int32> numberRange = Enumerable.Range(0,10);
List<NumberObject> numberList = new List<NumberObject>();
foreach (Int32 item in numberRange)
{
numberList.Add(new NumberObject() { Number = item });
}
return numberList;
}
public IEnumerable<NumberObject> GetNumbersWithLambda()
{
IEnumerable<Int32> numberRange = Enumerable.Range(0, 10);
IEnumerable<NumberObject> numbers = numberRange.
Select(number => new NumberObject() { Number = number });
return numbers;
}
private void runGetNumbers(Func<IEnumerable<NumberObject>> getNumbersFunction, Int32 numberOfTimesToRun)
{
for (int i = 0; i < numberOfTimesToRun; i++)
{
IEnumerable<NumberObject> numbers = getNumbersFunction();
//numbers.Count();
numbers.Sum(item => item.Number);
//numbers.Average(item => item.Number);
}
}
[TestMethod]
public void record_speed_of_GetNumbers()
{
Int32 numberOfTimes = 10000000;
Console.WriteLine("Doing warmup... " +
TimeMethod(() => runGetNumbers(GetNumbersWithLambda, numberOfTimes)));
Console.WriteLine("GetNumbersWithoutLambda: " +
TimeMethod(() => runGetNumbers(GetNumbersWithoutLambda, numberOfTimes)) + " milliseconds");
Console.WriteLine("GetNumbersWithLambda: " +
TimeMethod(() => runGetNumbers(GetNumbersWithLambda, numberOfTimes)) + " milliseconds");
}
static long TimeMethod(Action methodToTime)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
methodToTime();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
Below is the output from the test:
Doing warmup... 7560
GetNumbersWithoutLambda: 14779 milliseconds
GetNumbersWithLambda: 7626 milliseconds
The interesting this is that the "warmup" run actually does not seem to apply in this case.