2008-12-01 126 views
10

No tengo mucha experiencia con C#, así que si alguien pudiera señalarme en la dirección correcta, lo agradecería mucho. Tengo un bucle foreach que hace referencia a una variable de un objeto. Deseo hacer otro ciclo foreach dentro del principal que compare (o realice acciones en) la variable actual con el resto de las variables en la matriz del objeto. Tengo el siguiente código:C# foreach dentro de un bucle Foreach

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

    } 

Respuesta

15

Cada vez que se ejecuta foreach, (incluso mientras anidarlas) el enumerador interna debe "nueva" un iterador nuevo para usted, hay no debería ser ningún problema con eso. Los problemas surgen cuando agrega o elimina elementos de la colección mientras todavía está iterando ...

Recuerde, en el foreach interno, asegúrese de que no está en el mismo elemento que el externo para cada uno es en

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 

por cierto, el mejor lugar para poner este código estaría en una propiedad GravityForce de la clase RigidBodyBase, entonces se podría simplemente escribir:

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

aunque dependiendo de lo que están haciendo aquí (¿moviendo todos los objetos?) pueden ser e ¿Alguna otra oportunidad para refactorizar ... También consideraría tener una propiedad separada para las "otras" fuerzas, y hacer que TotalForce Property haga la suma de la Fuerza de Gravedad y las "otras" Fuerzas?

+0

Me gusta más esta respuesta porque, por lo que he leído, el ciclo foreach es más eficiente para el ciclo for. – wcm

-3

En este caso, es probable que sea mejor utilizar un habitual de bucle con un índice a qué elemento que se encuentra. Tratar de iterar sobre la misma colección dentro de su propio bucle foreach causará problemas.

+0

Estoy bastante seguro de que obtiene un nuevo enumerador con el segundo bucle foreach, por lo que no debería encontrarse con ningún problema. –

+0

sí, eso es correcto, al menos para cualquier clase de colección correctamente escrita ... Siempre es posible que algún desarrollador que escriba una clase de colección de framework personalizada implementará esto incorrectamente, pero para cualquier cosa de MS u otra fuente confiable, esto no es un problema . –

+0

Sí, lo siento, no sé dónde está mi cabeza hoy. Aunque, como mencionó Charles, obtienes errores si tratas de cambiar la colección (agregar o eliminar) mientras estás iterando sobre ella. – Kibbee

2

En mi humilde opinión, debería ser posible, aunque realmente debería considerar la sugerencia de Kibbee. Tal vez se puede optimizar de esa manera también (por ejemplo, como esto :)

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

No veo ningún problema con esto, siempre y cuando no cambie el doc. Las piezas dentro del lazo interno, ya que esto haría que las cosas exploten. Pero en teoría esto funcionaría. En cuanto a la optimización, no estoy seguro de si es mejor, pero es posible.

1

Bueno, este es un algoritmo O (n^2), pero supongo que no tiene otra opción aquí. ¿Qué hay de encapsular más de su lógica en otro método? Esto hace que la cosa simplemente vieja sea más legible.

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

... 

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