Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重构嵌套的foreach语句_C# - Fatal编程技术网

C# 重构嵌套的foreach语句

C# 重构嵌套的foreach语句,c#,C#,我有一个嵌套的foreach集合(迭代一组对象,然后查看每个对象内部)的方法。我在一本书中看到了一个很好的模式,使其更加优雅,但我记不起/找不到代码示例。否则我怎么能让这更整洁呢 代码只是一个典型的嵌套foreach语句,因此我没有提供代码示例。您必须更具体地说明“更优雅”的含义,因为在我看来,嵌套foreach并没有什么特别不优雅的地方 也就是说,.NET3.5及更高版本中的LINQ扩展方法可以提供帮助(特别是SelectMany) 公共类Foo { 公共列表字符串{get;set;} } .

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


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

您必须更具体地说明“更优雅”的含义,因为在我看来,嵌套
foreach
并没有什么特别不优雅的地方

也就是说,.NET3.5及更高版本中的LINQ扩展方法可以提供帮助(特别是
SelectMany

公共类Foo
{
公共列表字符串{get;set;}
}
...
List foos=新列表();
foreach(foos.SelectMany中的stringstr(f=>f.Strings))
{
...
}

您可以使用LINQ SelectMany操作符:

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

你在想这样的事情吗

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()));
public类对象{
公共列表其他{get;set;}
}
公共类对象{
public void DoIt(){}
}
var theList=新列表();
theList.ForEach(yo=>yo.Others.ForEach(oo=>oo.DoIt());
之前:

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

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

显而易见的解决办法是将其扁平化为方法

旧的:

新的:


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

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

我建议用你循环的第二件事创建一个
字典。然后在
foreach
中,只需使用
字典
查找所需的值

更新了嵌入的示例
foreach
Dictionary
备选方案:

List itemAs=新列表{
新项目a{id=1,number=10},
新项目a{id=2,number=15},
新项目a{id=3,number=20}
};
List itemBs=新列表{
新项目b{id=1,rate=100},
新项目b{id=2,rate=150},
新项目b{id=3,rate=200}
};
List itemABs=新列表();
//嵌入式foreach
foreach(itemAs中的ItemA ItemA)
{
foreach(ItemB中的ItemB ItemB)
{
if(itemA.id==itemB.id)
{
ItemAB ItemAB=newitemab{id=itemA.id,number=itemA.number,rate=itemB.rate};
添加(itemAB);
}
}
}
//使用字典作为查找
Dictionary itemBLookup=itemBs.ToDictionary(x=>x.id,y=>y);
foreach(itemAs中的ItemA ItemA)
{
TryGetValue(itemA.id,out ItemB ItemB);
ItemAB ItemAB=newitemab{id=itemA.id,number=itemA.number,rate=itemB.rate};
添加(itemAB);
}

此注释只是一个典型的注释,因此我没有提供注释!;-)我想起了Eric Lippert关于继续进行外循环的讨论:
ForEach
List
上的一种方法,而不是LINQ。@Adam Robinson:尽管人们可以(非常)容易地在
IEnumerable
上编写一个
ForEach
扩展方法,它的工作原理与
List
完全相同。它与此类似(可数)。谢谢。如果它是递归的,可能会导致堆栈溢出。想过使用队列进行宽度优先遍历吗?很好的参考!我猜你指的是队列或堆栈而不是字典。请查找图遍历算法,然后更新你的答案。我想的场景是,你有两个列表,并且它们在某些pro上匹配perty,您希望使用两个列表中对象的属性来执行其他操作,例如使用这两个列表中的属性构建另一个对象列表。我将用一个示例更新我的答案。
foreach(Order o in Customers.SelectMany(c => c.Orders))
{
  o.Dance();
}
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...
    }
}