Is one of them faster for cycles than the other?

for (var keyValue = 0; keyValue < dwhSessionDto.KeyValues.Count; keyValue++) {...} var count = dwhSessionDto.KeyValues.Count; for (var keyValue = 0; keyValue < count; keyValue++) {...} 

I know the difference between the two, but is one of them faster than the other? I think the second is faster.

+7
c #
source share
7 answers

Yes, the first version is much slower. In the end, I assume that you are dealing with these types:

 public class SlowCountProvider { public int Count { get { Thread.Sleep(1000); return 10; } } } public class KeyValuesWithSlowCountProvider { public SlowCountProvider KeyValues { get { return new SlowCountProvider(); } } } 

Here, your first cycle will take ~ 10 seconds, while your second cycle will take ~ 1 second.

Of course, you can argue that the assumption that you are using this code is unjustified, but I believe that the correct answer will depend on the respective types, and the question does not indicate what these types are.

Now, if you are really dealing with a type where access to KeyValues and Count cheap (which is likely), I would not expect that there would be a big difference. Keep in mind, I almost always prefer to use foreach , where possible:

 foreach (var pair in dwhSessionDto.KeyValues) { // Use pair here } 

This way you will never need an account. But then you did not say what you are trying to do inside the loop. (Hint: for more helpful answers, provide more information .)

+39
source share

depends on how difficult it is to calculate dwhSessionDto.KeyValues.Count , if its just a pointer to an int , then the speed of each version will be the same. However, if the Count value needs to be calculated, then it will be calculated every time and, therefore, impedes execution.

EDIT - contains code demonstrating that the condition is always reevaluated

 public class Temp { public int Count { get; set; } } static void Main(string[] args) { var t = new Temp() {Count = 5}; for (int i = 0; i < t.Count; i++) { Console.WriteLine(i); t.Count--; } Console.ReadLine(); } 

Conclusion 0, 1, 2 - only!

+6
source share

See comments for reasons why this answer is incorrect.

If there is a difference, then vice versa: Indeed, the first may be faster. This is because the compiler recognizes that you iterate from 0 to the end of the array, and therefore it can exclude border checks in a loop (ie. When accessing dwhSessionDTo.KeyValues[i] ).

However, I believe that the compiler applies this optimization only to arrays, so there probably won't be any difference here.

+1
source share

It is impossible to say without knowing the dwhSessionDto.KeyValues.Count implementation and the loop body.

Suppose the global variable bool foo = false; and then the following implementation:

 /* Loop body... */ { if(foo) Thread.Sleep(1000); } /* ... */ public int Count { get { foo = !foo; return 10; } } /* ... */ 

Now the first cycle will run about twice as fast as the second, D

However, assuming a nonmonic implementation, the second is likely to be faster.

+1
source share

Not. There is no difference in performance between the two cycles. With JIT and Code Optimization this makes no difference.

0
source share

There is no difference, but why do you think there is a difference, can you post your findings?

if you see insert implementation in a dictionary with a reflector

 private void Insert(TKey key, TValue value, bool add) { int freeList; if (key == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (this.buckets == null) { this.Initialize(0); } int num = this.comparer.GetHashCode(key) & 0x7fffffff; int index = num % this.buckets.Length; for (int i = this.buckets[index]; i >= 0; i = this.entries[i].next) { if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key)) { if (add) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } this.entries[i].value = value; this.version++; return; } } if (this.freeCount > 0) { freeList = this.freeList; this.freeList = this.entries[freeList].next; this.freeCount--; } else { if (this.count == this.entries.Length) { this.Resize(); index = num % this.buckets.Length; } freeList = this.count; this.count++; } this.entries[freeList].hashCode = num; this.entries[freeList].next = this.buckets[index]; this.entries[freeList].key = key; this.entries[freeList].value = value; this.buckets[index] = freeList; this.version++; 

}

Count is an internal member of this class that increments every element that you insert in the dictionary

therefore, I believe that there is no difference whatsoever.

0
source share

The second version can be faster sometimes. The fact is that this condition is reevaluated after each iteration, so if, for example, the “Get” getter actually considers elements in IEnumerable or interacts with the / etc database, this slows down.

So, I would say that if you do not affect the "Count" value in the "for", the second version is more secure.

0
source share

All Articles