开发者

Method execution inside loop declaration

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 */
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜