Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance difference for control structures 'for' and 'foreach' in C#

Which code snippet will give better performance? The below code segments were written in C#.

1.

for(int tempCount=0;tempCount<list.count;tempcount++) {     if(list[tempCount].value==value)     {         // Some code.     } } 
foreach(object row in list) {     if(row.value==value)     {         //Some coding     } } 
like image 914
Kthevar Avatar asked Jul 14 '09 11:07

Kthevar


People also ask

Which is faster foreach or for?

The forloop is faster than the foreach loop if the array must only be accessed once per iteration.

Do the for and foreach loop have a similar performance?

Foreach performance is approximately 6 times slower than FOR / FOREACH performance. The FOR loop without length caching works 3 times slower on lists, comparing to arrays. The FOR loop with length caching works 2 times slower on lists, comparing to arrays.

What is the difference between for and foreach?

foreach is useful when iterating all of the items in a collection. for is useful when iterating overall or a subset of items. The foreach iteration variable which provides each collection item, is READ-ONLY, so we can't modify the items as they are iterated. Using the for syntax, we can modify the items as needed.

Which is better for or foreach in C#?

The difference between for and foreach in C# is that for loop is used as a general purpose control structure while foreach loop is specifically used for arrays and collections. In brief, both helps to execute code repeatedly but foreach loop is more specific to arrays and collections.


2 Answers

Well, it partly depends on the exact type of list. It will also depend on the exact CLR you're using.

Whether it's in any way significant or not will depend on whether you're doing any real work in the loop. In almost all cases, the difference to performance won't be significant, but the difference to readability favours the foreach loop.

I'd personally use LINQ to avoid the "if" too:

foreach (var item in list.Where(condition)) { } 

EDIT: For those of you who are claiming that iterating over a List<T> with foreach produces the same code as the for loop, here's evidence that it doesn't:

static void IterateOverList(List<object> list) {     foreach (object o in list)     {         Console.WriteLine(o);     } } 

Produces IL of:

.method private hidebysig static void  IterateOverList(class [mscorlib]System.Collections.Generic.List`1<object> list) cil managed {   // Code size       49 (0x31)   .maxstack  1   .locals init (object V_0,            valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_1)   IL_0000:  ldarg.0   IL_0001:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<object>::GetEnumerator()   IL_0006:  stloc.1   .try   {     IL_0007:  br.s       IL_0017     IL_0009:  ldloca.s   V_1     IL_000b:  call       instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()     IL_0010:  stloc.0     IL_0011:  ldloc.0     IL_0012:  call       void [mscorlib]System.Console::WriteLine(object)     IL_0017:  ldloca.s   V_1     IL_0019:  call       instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()     IL_001e:  brtrue.s   IL_0009     IL_0020:  leave.s    IL_0030   }  // end .try   finally   {     IL_0022:  ldloca.s   V_1     IL_0024:  constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>     IL_002a:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()     IL_002f:  endfinally   }  // end handler   IL_0030:  ret } // end of method Test::IterateOverList 

The compiler treats arrays differently, converting a foreach loop basically to a for loop, but not List<T>. Here's the equivalent code for an array:

static void IterateOverArray(object[] array) {     foreach (object o in array)     {         Console.WriteLine(o);     } }  // Compiles into...  .method private hidebysig static void  IterateOverArray(object[] 'array') cil managed {   // Code size       27 (0x1b)   .maxstack  2   .locals init (object V_0,            object[] V_1,            int32 V_2)   IL_0000:  ldarg.0   IL_0001:  stloc.1   IL_0002:  ldc.i4.0   IL_0003:  stloc.2   IL_0004:  br.s       IL_0014   IL_0006:  ldloc.1   IL_0007:  ldloc.2   IL_0008:  ldelem.ref   IL_0009:  stloc.0   IL_000a:  ldloc.0   IL_000b:  call       void [mscorlib]System.Console::WriteLine(object)   IL_0010:  ldloc.2   IL_0011:  ldc.i4.1   IL_0012:  add   IL_0013:  stloc.2   IL_0014:  ldloc.2   IL_0015:  ldloc.1   IL_0016:  ldlen   IL_0017:  conv.i4   IL_0018:  blt.s      IL_0006   IL_001a:  ret } // end of method Test::IterateOverArray 

Interestingly, I can't find this documented in the C# 3 spec anywhere...

like image 92
Jon Skeet Avatar answered Oct 24 '22 16:10

Jon Skeet


A for loop gets compiled to code approximately equivalent to this:

int tempCount = 0; while (tempCount < list.Count) {     if (list[tempCount].value == value)     {         // Do something     }     tempCount++; } 

Where as a foreach loop gets compiled to code approximately equivalent to this:

using (IEnumerator<T> e = list.GetEnumerator()) {     while (e.MoveNext())     {         T o = (MyClass)e.Current;         if (row.value == value)         {             // Do something         }     } } 

So as you can see, it would all depend upon how the enumerator is implemented versus how the lists indexer is implemented. As it turns out the enumerator for types based on arrays are normally written something like this:

private static IEnumerable<T> MyEnum(List<T> list) {     for (int i = 0; i < list.Count; i++)     {         yield return list[i];     } } 

So as you can see, in this instance it won't make very much difference, however the enumerator for a linked list would probably look something like this:

private static IEnumerable<T> MyEnum(LinkedList<T> list) {     LinkedListNode<T> current = list.First;     do     {         yield return current.Value;         current = current.Next;     }     while (current != null); } 

In .NET you will find that the LinkedList<T> class does not even have an indexer, so you wouldn't be able to do your for loop on a linked list; but if you could, the indexer would have to be written like so:

public T this[int index] {        LinkedListNode<T> current = this.First;        for (int i = 1; i <= index; i++)        {             current = current.Next;        }        return current.value; } 

As you can see, calling this multiple times in a loop is going to be much slower than using an enumerator that can remember where it is in the list.

like image 20
Martin Brown Avatar answered Oct 24 '22 15:10

Martin Brown