I had a long debate last night about the effeciences of for loops, for each loops, and the instantiation of variables. Take a look at the following loops:
//Loop #1
MyObject obj = null;
for (int i = 0; i < myObjectCollection.Count; i++)
{
obj = myObjectCollection.Count[i];
//Do something with obj...
}
OR
//Loop #2
for (int i = 0; i < myObjectCollection.Count; i++)
{
MyObject obj = myObjectCollection.Count[i];
//Do something with obj...
}
Essentially both of these loops do the same thing. However I have a few questions:
1) In loop #2 it appears that "obj" gets instantiated each time through the loop therefore allocating a new location in the stack. Is this correct or does the compiler optimize this to allow the variable to remain in the same location each time just passing it a new reference to the object in the collection?
2) In either loop is it necessary/more effecient to set "obj = null" at any point to speed up garbage collection?
3) In general which of these is more effecient and why?
Thanks,
Micah Martin
AlanPosted Nov 7, 2007, 12:30 PM
Micah MartinPosted Nov 7, 2007, 12:02 PM
Alan -
Thanks for the response. If there is no difference from an efficiency standpoint, would it then make more sense to use loop #2 since the "obj" variable will immediately fall out of scope when the loop terminates as opposed to having the variable declared outside of the loop?
AlanPosted Nov 7, 2007, 11:56 AM
Hi Micah,
1. When the JIT compiler compiles a method, it allocates a slot on the stack to hold each local variable used in that method, whether the variable is declared within a loop or not. So, in both loops, the same memory slot is always used for the 'obj' variable and it doesn't therefore make any difference whether you declare it inside or outside the loop.
2. All objects referenced by local variables will become eligible for garbage collection when the method ends, provided there are no other external references to those objects. However, if you no longer need those objects, it may speed up GC if you set the variables to null before the method ends depending on the state of the heap at the time. If the objects are holding onto any unmanaged resources, it may also be sensible to call the Dispose() method first.
3. As the code stands, the second loop is slightly more efficient because the 'obj' variable is being set to null before the first loop starts. However, this is unnecessary - the code will still compile if you leave it unassigned - in which case there is nothing to choose between the two from an efficiency viewpoint.