2010-03-12 12 views
9

Ich habe eine Methode mit einer verschachtelten foreach Sammlung (iterieren Sie eine Reihe von Objekten und dann in jedes Objekt). Ich sah in einem Buch ein gutes Muster, um dies viel eleganter zu machen, aber ich kann mich nicht an das Codebeispiel erinnern. Wie sonst könnte ich das aufgeräumter machen?Refactoring verschachtelte Foreach-Anweisung

Der Code ist nur eine typische verschachtelte foreach Anweisung, also habe ich kein Codebeispiel bereitgestellt.

+8

Dieser Kommentar ist nur ein typischer Kommentar, also habe ich keinen Kommentar abgegeben! ;-) –

+2

Ich erinnere mich an Eric Lipperts Diskussion über die Fortsetzung einer äußeren Schleife: http://blogs.msdn.com/ericlippert/archive/2010/01/11/continuing-to-an-outer-loop.aspx – Brian

Antwort

5

Die naheliegende Lösung ist in Methoden abzuflachen.

Alt:

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

Neu:

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

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

Andere Antworten hier scheinen auf Linq fokussiert zu werden, und ich würde zustimmen, dass, wenn Ihr Schleifen haben keine Nebenwirkungen (dh Sie versuchen nur, einige Informationen aus der innersten Schleife zu extrahieren), dann kannst du das Ganze wahrscheinlich mit ein oder zwei einfachen Linq-Anweisungen umschreiben. Wenn Nebenwirkungen auftreten, folgen Sie einfach der bewährten Praxis von Unterprogrammen.

+0

Es war ähnlich (IEnumerable zurückgeben). Vielen Dank. – dotnetdev

11

Sie werden spezifischere darüber haben, was Sie „elegantere“ bedeuten in Bezug auf, wie IMO gibt es nichts besonders unelegant über eine verschachtelte foreach.

Das gesagt, die LINQ-Erweiterung Methoden in .NET 3.5 und höher kann helfen (speziell 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)) 
{ 
    ... 
} 
0

Denken Sie an so etwas?

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())); 
+0

'ForEach' ist eine Methode auf' List ', ** nicht ** LINQ. –

+0

@Adam Robinson, du hast recht ... –

+0

@Adam Robinson: Obwohl man (')' '' ''Enumerable ' (') einfach eine 'ForEach'-Erweiterungsmethode schreiben kann, funktioniert das genau so wie für' List '. –

4

Bevor:

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

After:

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

Es ist schwierig, eine Antwort ohne Kontext oder Code-Snippet zu geben. Martin Fowler hat jedoch einen wirklich guten Artikel über das Refactoring von Loops in LINQ-Pipelines, die man finden kann here (weiß, dass dies eine alte Frage ist, hoffentlich werden zukünftige Leser davon profitieren!).