tags:

views:

1874

answers:

6

I don't have too much experience with C# so if someone could point me in the right direction I would greatly appreciate it. I have a foreach loop that references a variable of an object. I wish to make another foreach loop inside the main one that compares (or performs actions on) the current variable to the rest of the variables in the array of the object. I have the following code:

// Integrate forces for each body.
 foreach (RigidBodyBase body in doc.Bodies)
 {
  // Don't move background-anchored bodies.
  if (body.anchored) continue;

        // This is where we will add Each Body's gravitational force 
        //  to the total force exerted on the object.

        // For each other body, get it's point and it's mass.

            // Find the gravitational force exterted between target body and looped body.
                // Find distance between bodies.
                    // vector addition
                // Force = G*mass1*mass2/distance^2
            // Find vector of that force.
            // Add Force to TotalGravityForce
        // loop until there are no more bodies.
        // Add TotalGravityForce to body.totalForce

 }
A: 

In this case, it's probably better to use a regular for loop with an index to what element you are on. Trying to iterate over the same collection withing it's own foreach loop will cause problems.

Kibbee
I'm pretty sure you get a new enumerator with the 2nd foreach loop, so you shouldn't run into any issues.
Jon Tackabury
yes that is correct, at least for any properly written collection class... It's always possible that some developer writing a custom framework collection class will implement this incorrectly, but for anything from MS, or other reputable source, this is not an issue.
Charles Bretana
Yeah, sorry, I don't know where my head is today. Although as Charles mentioned, you do get errors if you try to change the collection (add or remove) as you are iterating over it.
Kibbee
It doesn't matter if you get a new enumerator or not, what matters is that you're modifying the collection the first foreach loop is iterating, therefore causing errors. Not the best solution, IMHO, but +1
Ricardo Villamil
+1  A: 

IMHO it should be possible, although you should really consider Kibbee's suggestion. Maybe you can optimize it that way too (for example, like this:)

int l = doc.Bodies.Count;
for ( int i = 0; i < l; i++ )
    for ( int j = i + 1; j < l; j++ )
        // Do stuff
Vilx-
+11  A: 

Each time you execute foreach, (even while nesting them) the internal Enumerator should "new" up a new iterator for you, there should not be any issue with that. The issues come about when you are adding, or removing items from the collection while you are still iterating...

Remember, in the inner foreach, to check to make sure you are not on the same item as the outer for each is on

  foreach( RigidBodyBase body in doc.Bodies)
     foreach ( RigidBodyBase otherBody in doc.Bodies)
         if (!otherBody.Anchored && otherBody != body)  // or otherBody.Id != body.Id -- whatever is required... 
              // then do the work here

by the way, the best place to put this code would be in a GravityForce property of the RigidBodyBase class, Then you could just write:

   foreach (RigidBodyBase body in doc.Bodies)
       body.TotalForce += body.GravityForce;

although depending on what you're doing here (moving all objects?) they're may be even more opportunity for refactoring... I'd also consider having a separate property for the "other" forces, and have TotalForce Property do the summing of the Gravity Force and the "other" Forces?

Charles Bretana
I like this answer best because, from what I have read, the foreach loop is more efficient for the for loop.
wcm
+1  A: 

I don't see a problem with this as long as you don't change doc.Bodies inside the inner loop, as this would cause things to blow up. But in theory this would work. As for optimization I'm not sure if it is best, but it is possible.

Joshua Hudson
+1  A: 

There is no problem in nesting foreach iterations over the same collection as long as you are doing it in a read only manner, but trying to edit the contents of a collection that you are iterating over using foreach will cause you problems no matter if its nested or not.

StingyJack
+1  A: 

Well, this is a O(n^2) algorithm, but I guess you have no choice here. How about encapsulating more of your logic into another method. This makes the thing just plain old more readable.

foreach (RigidBodyBase body in doc.Bodies)        
{                
   Integrateforces(ref body, Bodies);
}

...

public void Integrateforces(RigidBodyBase out body, RigidBodyBase[] Bodies)
{
  //Put your integration logic here
}
Charles Graham