Are the limits of for loops calculated once or with each loop?
For this it it calculated once, or more likely 0 times.
The compiler will optimize the multiplication away for you.
However this is not always the case if you have something like.
for(int i=0; i<someFunction();i++)
{
//Do something!
}
Because the compiler is not always able to see what someFunction
will return. So even if someFunction
does return a constant value every time, if the compiler doesn't know that, it cannot optimize it.
EDIT: As MainMa said in a comment, you are in this situation you can eliminate the cost by doing something like this:
int limit = someFunction();
for(int i=0; i<limit ;i++)
{
//Do something!
}
IF you are certain that the value of someFunction()
will not change during the loop.
This is one of the most commonly misunderstood behavior of loops in C#.
Here's what you need to know:
Loop bounds calculations, if non-constant and involving a variable, property-access, function call, or delegate invocation will re-compute the value of the bounds before each iteration of the loop.
So, for example:
for( int i = 0; i < 1234*1234; i++ ) { ... }
In this case, the expression 1234*1234
is a compile time constant, and as a result will not be recomputed on each iteration. In fact, it is calculated at compile time and replaced with a constant.
However, in this case:
int k = 10;
for( int i = 0; i < k; i++ ) { k -= 1; ... }
The value of k
has to be examined on each iteration. After all it can change .. in in this example does. Fortunately, since k
is simply a local variable, the cost of accessing it is very low - and in many cases it will either be retained in the local CPU cache or perhaps even maintained in a register (depending on how the JIT processes and emits the machine code).
In the case of something like the following:
IEnumerable<int> sequence = ...;
for( int i = 0; i < sequence.Count(); i++ ) { ... }
The cost of computing the sequence.Count()
can be quite expensive. And since it's evaluated on each iteration of the loop it can add up quickly.
The compiler cannot optimize away the calls to methods or properties that occur within the loop bounds expression because they may also change with each iteration. Imagine if the loop above was written as:
IEnumerable<int> sequence = ...;
for( int i = 0; i < sequence.Count(); i++ ) {
sequence = sequence.Concat( anotherItem );
}
Clearly sequence
is changing on each iteration ... and therefore the Count()
is likely to be different on each iteration. The compiler does not attempt to perform some static analysis to determine whether the loop bounds expression could be constant ... that would be extremely complicated, if not impossible. Instead, it assumes that if the expression is not a constant it must be evaluated on each iteration.
Now, in most cases, the cost of computing the bounds constraint for a loop is going to be relatively inexpensive, so you don't have to worry about it. But you do need to understand how the compiler treats loop bounds like this. Also, as a developer you need to be careful about using properties or methods that have side-effects as part of a bounds expression - after all, these side effects will occur on each iteration of the loop.
Actually that won't compile because it will overflow but if you make it a smaller number and open up Reflector you will find something like this.
for (int i = 0; i < 0x3cf7b0; i++)
{
}