C#中的foreach循环嵌套

13

我对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

    }
5个回答

18
每次执行foreach时(即使嵌套),内部枚举器都应该为您“new”一个新迭代器,这没有任何问题。当您在迭代时仍然添加或删除集合中的项时,问题就会出现...
请记住,在内部循环中,要检查确保您不在与外部循环相同的项上。
  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

顺便说一句,将此代码放置的最佳位置是RigidBodyBase类的GravityForce属性中,然后您只需编写:

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

虽然具体操作视情况而定(是移动所有物体吗?)可能还有更多的重构机会......我也会考虑为“其他”力量单独设立一个属性,并让TotalForce属性对重力力量和“其他”力量进行求和?


我最喜欢这个答案,因为根据我的阅读,foreach循环比for循环更高效。 - wcm

2

我认为这是可能的,尽管你应该认真考虑Kibbee的建议。也许你可以通过这种方式进行优化(例如,像这样:)

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

1

只要你不在内部循环中更改 doc.Bodies,这个东西看起来没有什么问题,否则会导致事情崩溃。但从理论上讲,这是可行的。至于优化,我不确定它是否最好,但是它是可能的。


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 Tackabury
是的,对于任何正确编写的集合类来说都是正确的。当然,有些开发人员编写自定义框架集合类时可能会实现不正确,但对于来自微软或其他值得信赖的来源的任何内容,这都不是问题。 - Charles Bretana
是的,抱歉,我今天有些恍惚。虽然正如Charles所提到的,如果您在迭代过程中尝试更改集合(添加或删除),则会出现错误。 - Kibbee
无论你是否获得了一个新的枚举器,重要的是你正在修改第一个foreach循环正在迭代的集合,从而导致错误。在我看来,这不是最好的解决方案,但还是点个赞。 - Ricardo Villamil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接