I was looking at the performance of a site I'm developing and I came across some code I wrote:
foreach (WorkItem wi in p.getWorkItems(dateFrom, dateTo))
{
someFunction(wi);
}
In the above code, does the p.getWorkItems
method run each time th开发者_StackOverflowe loop executes? Or does it execute once, keep the result object in memory and just increment the pointer to which object it's using? The reason is that getWorkItems
does a substantial amount of stuff behind the scenes (comparisons, sorting, other queries) and so it would be best not to execute this over and over. If that's the case then I'd be better off doing it as below:
List<WorkItem> workload = p.getWorkItems(dateFrom, dateTo);
for (int i = 0; i < workload.Count; i++)
{
someFunction(workload[i]);
}
It's written in C# but I'm assuming that the answer will be applicable to most similar languages..
You should understand how a foreach
loop is translated into C# code. From 8.8.4 of the C# language specification, your loop
foreach (WorkItem wi in p.getWorkItems(dateFrom, dateTo)) {
someFunction(wi);
}
becomes
var enumerator = p.getWorkItems(dateFrom, dateTo).GetEnumerator();
try {
WorkItem wi;
while(enumerator.MoveNext()) {
wi = (WorkItem)enumerator.Current;
someFunction(wi);
}
}
finally {
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
}
Thus, it is CLEAR that p.getWorkItems
executes exactly once.
Or does it execute once, keep the result object in memory and just increment the pointer to which object it's using?
Yes.(*) You can prove this to yourself by putting a print statement in getWorkItems
.
(*) Unless the result object calls into getWorkItems
recursively.
p.getWorkItems
is called only once. The result is stored in memory and the foreach loops iterates for the result object in memory.
If this would not be the case, then each time the method will return the new list and foreach will never end.
A small application for proof:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
foreach(var i in GetCol()) {
Console.WriteLine(i);
}
}
private static List<int> GetCol() {
Console.WriteLine("I have been called");
return new List<int>(){1, 2, 3, 4};
}
}
/* Output
I have been called
1
2
3
4 */
精彩评论