C # foreach в цикле foreach

Asked
Viewd24176

11

У меня нет большого опыта работы с C #, поэтому, если кто-то может указать мне правильное направление, я был бы очень признателен. У меня есть цикл foreach, который ссылается на переменную объекта. Я хочу создать еще один цикл 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

    }
 
24176

5 ответов

17

Каждый раз, когда вы выполняете foreach (даже при их вложении), внутренний Enumerator должен «создавать» для вас новый итератор, с этим не должно быть никаких проблем. Проблемы возникают, когда вы добавляете или удаляете элементы из коллекции, пока вы все еще повторяете ...

Помните, что во внутреннем foreach необходимо убедиться, что вы находитесь не в том же элементе, что и внешний для каждого из них

   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
 

кстати, лучше всего разместить этот код в свойстве GravityForce класса RigidBodyBase. Тогда вы можете просто написать:

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

хотя в зависимости от того, что вы здесь делаете (перемещаете все объекты?), у них может быть еще больше возможностей для рефакторинга ... Я бы также подумал о том, чтобы иметь отдельное свойство для "других" сил и иметь TotalForce Собственность суммирует Силу Тяготения и «другие» Силы?

  • Мне больше всего нравится этот ответ, потому что, судя по тому, что я прочитал, цикл foreach более эффективен для цикла for.

    wcm01 декабря 2008, 17:57
2

ИМХО, это должно быть возможно, хотя вам действительно стоит принять во внимание предложение Кибби. Может, и так можно его оптимизировать (например, вот так :)

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

Ну, это алгоритм O (n ^ 2), но я думаю, у вас нет выбора. Как насчет инкапсуляции большей части вашей логики в другой метод. Это делает старый текст более читабельным.

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

...

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

В этом случае, вероятно, лучше использовать обычный цикл for с указанием того, на каком элементе вы находитесь. Попытка перебрать ту же коллекцию в собственном цикле foreach вызовет проблемы.

  • Я почти уверен, что вы получите новый перечислитель со вторым циклом foreach, поэтому у вас не должно возникнуть никаких проблем.

    Jon Tackabury01 декабря 2008, 17:57
  • Да, извините, я не знаю, где сейчас моя голова. Хотя, как упоминал Чарльз, вы получаете ошибки, если пытаетесь изменить коллекцию (добавить или удалить), когда вы повторяете ее.

    Kibbee01 декабря 2008, 18:35
  • Да, это правильно, по крайней мере, для любого правильно написанного класса коллекции ... Всегда возможно, что какой-то разработчик, пишущий собственный класс коллекции платформы, будет реализовывать это неправильно, но для чего-либо от MS или другого авторитетного источника это не проблема .

    Charles Bretana01 декабря 2008, 18:00
  • Неважно, получите вы новый перечислитель или нет, важно то, что вы изменяете коллекцию, и первый цикл foreach повторяется, что приводит к ошибкам. Не лучшее решение, ИМХО, но +1

    Ricardo Villamil01 декабря 2008, 18:40
1

Я не вижу в этом проблемы, пока вы не меняете doc.Bodies во внутреннем цикле, так как это может привести к взрыву. Но теоретически это сработает. Что касается оптимизации, я не уверен, что она лучше, но это возможно.