2008-12-01 25 views
10

Nie mam zbyt dużego doświadczenia z C#, więc jeśli ktoś mógłby wskazać mi właściwy kierunek, byłbym bardzo wdzięczny. Mam pętlę foreach, która odwołuje się do zmiennej obiektu. Chciałbym utworzyć kolejną pętlę foreach wewnątrz głównej, która porównuje (lub wykonuje akcje) z bieżącą zmienną z resztą zmiennych w tablicy obiektu. Mam następujący kod:C# foreach w pętli 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 

    } 

Odpowiedz

15

Każdorazowe wykonanie foreach (nawet podczas ich gniazdowania) wewnętrzna Enumerator powinien „nowy” w górę nowego iteratora dla ciebie, tam nie powinno to być żadnym problemem. Problemy pojawiają się podczas dodawania lub usuwania elementów z kolekcji, gdy wciąż trwa iterowanie ...

Pamiętaj, aby w wewnętrznym foreach sprawdzić, czy nie jesteś na tym samym przedmiocie co zewnętrzna każdy jest na

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 

przy okazji, to najlepsze miejsce, aby umieścić ten kod byłby w nieruchomości GravityForce klasy RigidBodyBase, to można po prostu napisać:

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

chociaż w zależności od tego, co czy robienie tutaj (przenoszenie wszystkich obiektów?) to może być e więcej możliwości refaktoryzacji ... Rozważałbym także posiadanie oddzielnej nieruchomości dla "innych" sił i czy TotalForce Property zsumuje siły grawitacji i "inne" siły?

+0

Najbardziej mi odpowiada ta odpowiedź, ponieważ z tego, co przeczytałem, pętla foreach jest bardziej wydajna dla pętli for. – wcm

-3

w tym przypadku, to chyba lepiej użyć zwykłej pętli for z indeksem do czego elementem której się znajdujesz. Próba iteracji w tej samej kolekcji z własną pętlą foreach spowoduje problemy.

+0

Jestem pewien, że otrzymujesz nowy moduł wyliczający z drugą pętlą foreach, więc nie powinieneś napotkać żadnych problemów. –

+0

Tak, to jest poprawne, przynajmniej dla jakiejkolwiek prawidłowo napisanej klasy kolekcji ... Zawsze jest możliwe, że jakiś programista piszący niestandardową klasę kolekcji ramek wdroży to niepoprawnie, ale dla niczego z MS lub innego renomowanego źródła, to nie jest problem . –

+0

Tak, przepraszam, nie wiem, gdzie dziś jest moja głowa. Chociaż, jak wspomniał Charles, pojawiają się błędy, jeśli próbujesz zmienić kolekcję (dodawać lub usuwać) podczas iteracji. – Kibbee

2

IMHO powinno być możliwe, chociaż naprawdę powinieneś rozważyć sugestię Kibbee. Być może można zoptymalizować w ten sposób zbyt (na przykład, jak ten :)

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

Nie widzę problemu z tym, o ile nie zmienisz doc.Bodies wewnątrz wewnętrznej pętli, ponieważ spowoduje to wysadzenie w powietrze. Ale teoretycznie to by działało. Jeśli chodzi o optymalizację, nie jestem pewien, czy jest najlepszy, ale jest to możliwe.

1

To jest algorytm O (n^2), ale chyba nie masz wyboru. Co powiesz na umieszczenie większej ilości logiki w innej metodzie. To sprawia, że ​​rzecz po prostu stara się bardziej czytelna.

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

... 

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