Update (23/02/2017)
There is another benchmark result published on 13 May 2016 at [C#: For Vs ForEach Vs While] which the benchmark tested with more data type and more details findings. You might want to have a read on it. The benchmark shows different times consumed for different data type.
Introduction
I have seen lots of arguments and different points of view about which is better practice among For Loop
and Foreach Loop
.
From the outcomes of the findings from the previous programmers, some of the conclusions of the researches were conflicting each other, and thus, this shows that the way .NET work with For Loop and Foreach Loop has changed from years to years. It seems that the development team of .NET Framework has improved and modified the workout logic of For Loop and Foreach throughout different version of milestone of .NET Framework releases.
After reading the valuable information from the articles, I have decided to do benchmark, to compare the performance between For Loop
and Foreach Loop
in figures.
The Benchmark Result (2013)
Measured in miliseconds. Default collection length: 30000000 . I try to increase the length, but receive exception of System.OutOfMemoryException.
Data Type | Collection Type | Loop Type | Test 1 | Test 2 | Test 3 | Average |
---|
int | int[] | For | 88.0051 | 83.0047 | 83.0048 | 84.672 |
int | int[] | Foreach | 83.0047 | 82.0047 | 81.0047 | 82.005 |
int | List<int> | For | 89.0051 | 84.0048 | 83.0048 | 85.338 |
int | List<int> | Foreach | 98.0056 | 98.0057 | 98.0056 | 98.006 |
int | ArrayList<int> | For | 188.0107 | 182.0104 | 182.0104 | 184.011 |
int | ArrayList<int> | Foreach | 445.0254 | 444.0254 | 445.0254 | 444.692 |
class | class[] | For | 98.0056 | 92.0052 | 92.0053 | 94.005 |
class | class[] | Foreach | 93.0053 | 93.0053 | 92.0052 | 92.672 |
class | List<class> | For | 107.0061 | 107.0061 | 108.0062 | 107.339 |
class | List<class> | Foreach | 136.0078 | 138.0078 | 137.0079 | 137.008 |
class | ArrayList<class> | For | 195.0111 | 195.0111 | 196.0112 | 195.344 |
class | ArrayList<class> | Foreach | 446.0255 | 443.0254 | 446.0255 | 445.025 |
Chart
Conclusion
Speed of Collections
- Array (Fastest)
- List
- ArrayList (Slowest)
Data Type - Operation
Array
Almost no difference between For Loop and Foreach Loop. Foreach Loop seems to be a bit faster.
List
For Loop is slightly faster than Foreach Loop
ArrayList
For Loop is about more than 2 times faster speed than Foreach Loop.
Codes Used to Run the Test
Declare Collections:
static int[] intArray = null;
static List<int> intList = null;
static ArrayList intArrayList = null;
static SampleClass[] scArray = null;
static List<SampleClass> scList = null;
static ArrayList scArrayList = null;
static int LengthTest = 30000000;
Initializing Collection:
byte[] ba = new byte[LengthTest];
Random rd = new Random();
rd.NextBytes(ba);
intArray = new int[ba.Length];
for (int h = 0; h < ba.Length; h++)
{
intArray[h] = ba[h];
}
intList = new List<int>();
intList.AddRange(intArray);
intArrayList = new ArrayList(intArray);
DateTime scStart = DateTime.Now;
scArray = new SampleClass[LengthTest];
for (int i = 0; i < scArray.Length; i++)
scArray[i] = new SampleClass();
scList = new List<SampleClass>(scArray);
scArrayList = new ArrayList(scArray);
A StringBuilder to collect information:
StringBuilder sb = new StringBuilder();
Sample of For Loop Test:
static void TestIntArrayFor()
{
string section = "int[] For Loop Test - Length = " + intArray.Length;
List<TimeSpan> lstTimespan = new List<TimeSpan>();
sb.AppendLine(section);
for (int round = 0; round < Round; round++)
{
DateTime start = DateTime.Now;
int total = 0;
for (int i = 0; i < intArray.Length; i++)
{
total += intArray[i];
}
lstTimespan.Add(DateTime.Now - start);
sb.AppendLine("Test " + (round + 1) + " : " + lstTimespan[round].TotalMilliseconds.ToString());
}
double ds = 0;
for (int b = 0; b < lstTimespan.Count; b++)
{
ds += lstTimespan[b].TotalMilliseconds;
}
sb.AppendLine("Average: " + (ds / 3).ToString("0.###") + " miliseconds");
sb.AppendLine();
}
Sample of Foreach Loop Test
static void TestClassArrayForeach()
{
string section = "Class[] Foreach Loop Test - Length = " + scArray.Length;
List<TimeSpan> lstTimespan = new List<TimeSpan>();
sb.AppendLine(section);
for (int round = 0; round < Round; round++)
{
DateTime start = DateTime.Now;
long total = 0;
foreach(SampleClass sc in scArray)
{
total += sc.Number;
}
lstTimespan.Add(DateTime.Now - start);
sb.AppendLine("Test " + (round + 1) + " : " + lstTimespan[round].TotalMilliseconds.ToString());
}
double ds = 0;
for (int b = 0; b < lstTimespan.Count; b++)
{
ds += lstTimespan[b].TotalMilliseconds;
}
sb.AppendLine("Average: " + (ds / 3).ToString("0.###") + " miliseconds");
}