重构嵌套的foreach语句

时间:2010-03-12 15:18:49

标签: c#

我有一个嵌套foreach集合的方法(迭代一组对象,然后查看每个对象)。我在一本书中看到了一个很好的模式,使这个更优雅,但不记得/找到代码示例。我怎么能让它更整洁?

代码只是一个典型的嵌套foreach语句,所以我没有提供代码示例。

7 个答案:

答案 0 :(得分:11)

你必须更加具体地说明你对“更优雅”的意思,因为对于嵌套的foreach,IMO没有什么特别的不优雅的

话虽如此,.NET 3.5及更高版本中的LINQ扩展方法可以提供帮助(特别是SelectMany)。

public class Foo
{
    public List<string> Strings { get; set; }
}

...

List<Foo> foos = new List<Foo>();

foreach(string str in foos.SelectMany(f => f.Strings))
{
    ...
}

答案 1 :(得分:7)

显而易见的解决方案是压缩方法。

旧:

void SubmitOrders()
{
    var orders = GetOrders();
    foreach (Order o in orders)
    {
        foreach (OrderDetail d in o.Details)
        {
            // Blah...
        }
    }
}

新:

void SubmitOrders()
{
    var orders = GetOrders()
    foreach (Order o in orders)
    {
        SubmitOrder(o);
    }
}

void SubmitOrder(Order order)
{
    foreach (OrderDetail d in order.Details)
    {
        // Blah...
    }
}

这里的其他答案似乎都集中在Linq上,我同意如果你的循环没有副作用(即你只是想从最里面的循环中提取一些信息),那么您可以使用一个或两个简单的Linq语句重写整个事物。如果涉及副作用,那么只需遵循经过时间考验的子程序实践。

答案 2 :(得分:5)

在:

foreach(Customer c in Customers)
{
  foreach(Order o in c.Orders)
  {
    o.Dance();
  }
}

后:

foreach(Order o in Customers.SelectMany(c => c.Orders))
{
  o.Dance();
}

答案 3 :(得分:1)

您可以使用LINQ SelectMany运算符:

foreach (var bar in model.FooCollection.SelectMany(f => f.Bars))
{
  // Do Stuff
}

http://www.hookedonlinq.com/SelectManyOperator.ashx

答案 4 :(得分:1)

很难在没有任何上下文或代码段的情况下给出答案。但是,Martin Fowler有一篇关于重构LINQ管道循环的文章非常好,可以找到here(虽然这是一个老问题,所以希望未来的读者会受益!)。

答案 5 :(得分:0)

你在想这样的事吗?

public class YourObject{
   public List<OtherObject> Others { get; set; }
}

public class OtherObject{
   public void DoIt(){}
}

var theList = new List<YourObject>();

theList.ForEach(yo => yo.Others.ForEach(oo => oo.DoIt()));

答案 6 :(得分:0)

我建议您在循环遍历的第二件事中创建一个Dictionary。然后在foreach内部,只需将Dictionary用作所需值的查找即可。

已更新,其中嵌入了foreachDictionary替代示例:

List<ItemA> itemAs = new List<ItemA> { 
    new ItemA { id = 1, number = 10 },
    new ItemA { id = 2, number = 15 },
    new ItemA { id = 3, number = 20 }
};
List<ItemB> itemBs = new List<ItemB> {
    new ItemB { id = 1, rate = 100 },
    new ItemB { id = 2, rate = 150 },
    new ItemB { id = 3, rate = 200}
};
List<ItemAB> itemABs = new List<ItemAB>();
// embedded foreach
foreach(ItemA itemA in itemAs)
{
    foreach(ItemB itemB in itemBs)
    {
        if(itemA.id == itemB.id)
        {
            ItemAB itemAB = new ItemAB { id = itemA.id, number = itemA.number, rate = itemB.rate };
            itemABs.Add(itemAB);
        }
    }
}
// using dictionary as lookup
Dictionary<int, ItemB> itemBLookup = itemBs.ToDictionary(x => x.id, y => y);
foreach (ItemA itemA in itemAs)
{
    itemBLookup.TryGetValue(itemA.id, out ItemB itemB);
    ItemAB itemAB = new ItemAB { id = itemA.id, number = itemA.number, rate = itemB.rate };
    itemABs.Add(itemAB);
}