2010-03-12 15 views
9

Tengo un método con una colección anidada foreach (repito un conjunto de objetos y luego miro dentro de cada objeto). Vi en un libro un buen patrón para hacer esto mucho más elegante, pero no puedo recordar/encontrar el ejemplo del código. ¿De qué otra manera podría hacer esto más ordenado?Refactorización de declaración foreach anidada

El código es simplemente una declaración anidada típica foreach por lo que no he proporcionado una muestra de código.

+8

Este comentario es solo un comentario típico, ¡así que no he dado ningún comentario! ;-) –

+2

Me acuerdo de la discusión de Eric Lippert sobre la continuación de un ciclo externo: http://blogs.msdn.com/ericlippert/archive/2010/01/11/continuing-to-an-outer-loop.aspx – Brian

Respuesta

5

La solución obvia es aplanar en métodos.

antigua:

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

Nuevo:

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

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

Otras respuestas aquí parece estar centrado en LINQ, y yo estaría de acuerdo en que si sus bucles no tienen efectos secundarios (es decir, simplemente están tratando de extraer algo de información del bucle más interno), entonces probablemente puedas reescribir todo usando una o dos declaraciones simples de Linq. Si se trata de efectos secundarios, simplemente siga la práctica comprobada de las subrutinas.

+0

Fue similar a esto (devolviendo IEnumerable). Gracias. – dotnetdev

11

vas a tener que ser más específico acerca de lo que quieres decir con respecto a "más elegante", como la OMI no hay nada particularmente poco elegante sobre un anidado foreach.

Dicho esto, los métodos de extensión LINQ en .NET 3.5 y posteriores pueden ayudar (específicamente 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

¿Está pensando en algo como esto?

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' es un método en' List ', ** not ** LINQ. –

+0

@ Adam Robinson, tienes razón ... –

+0

@ Adam Robinson: Aunque uno podría (muy) fácilmente escribir un método de extensión 'ForEach' en' IEnumerable 'que funciona exactamente como lo hace para' List '. –

4

Antes:

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

Después de:

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

Es difícil dar una respuesta sin ningún contexto o fragmento de código. Sin embargo, Martin Fowler tiene un artículo realmente bueno sobre la refactorización de bucles en tuberías de LINQ que se puede encontrar en here (aunque esta es una vieja pregunta, espero que los futuros lectores se beneficien).