Friday, April 24, 2009

Looping Over Lists

Here is a very common way to define a list of instances in .NET (in this example, a list of particles):


List<Particle> Particles = new List<Particle>();


There is a really good video on animation that includes the creation and application of particle emitters at this link:

http://videos.visitmix.com/MIX09/T12F

The demo on Particles is about halfway through.

Also you can try an example created by Robby at:

http://labs.nerdplusart.com/particles/fullscreen.php

There are at least two ways you can loop through all the elements in a list -- a For loop and a ForEach loop. A For loop would look like this:



for (int i=0; i<Particles.count; i++)
{
var oParticle=Particles[i];
if ( oParticle.Age > oParticle.LifeTime)
{
LayoutRoot.Children.Remove(oParticle);
Particles.Remove(oParticle);
}
}

When I first did my implementation I used a ForEach loop, because I always use a ForEach -- the coding is simpler:



foreach (Particle oParticle in Particles)
if ( oParticle.Age > oParticle.LifeTime)
{
LayoutRoot.Children.Remove(oParticle);
Particles.Remove(oParticle);
}


In both cases the loop is (sooner or later) going to try to remove a particle object from the collection you are looping over. Removing it from the LayoutRoot.Children is never a problem because this connection is not currently locked by the loop, but calling Particles.Remove(oParticle) is a problem in the ForEach loop because the Particles collection is locked from editing (adds and removes) during the ForEach loop.

My first fix was to make a copy of the collection I was looping over. This is a bad idea because it really slows things down, and in a graphics animation, you need all the speed you can get.

So I went back and tried the For loop and realized why the experts selected that implementation. Even though the ith item is removed from the list, the collection does not automatically close up ranks and reindex all the items. Being aware of this distinction is extremely useful in certain applications.

No comments: