Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring nested foreach statement

Tags:

c#

I have a method with a nested foreach collection (iterate a set of objects and then look inside each object). I saw in a book a good pattern to make this much more elegant but cannot remember/find the code example. How else could I make this more tidy?

The code is just a typical nested foreach statement so I have not provided a code sample.

like image 204
GurdeepS Avatar asked Mar 12 '10 15:03

GurdeepS


People also ask

How do you refactor nested foreach loops?

I'd suggest creating a Dictionary out of the second thing you loop through. Then inside the foreach just use your Dictionary as a lookup for the value you want. I guess you mean a queue or stack instead of a dictionary. Please look up graph traversal algorithm and then update your answer.

Can you nest foreach loops?

The nesting operator: %:% I call this the nesting operator because it is used to create nested foreach loops. Like the %do% and %dopar% operators, it is a binary operator, but it operates on two foreach objects. It also returns a foreach object, which is essentially a special merger of its operands.


2 Answers

The obvious solution is to flatten into methods.

Old:

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

New:

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

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

Other answers here seem to be focused on Linq, and I would agree that if your loops have no side-effects (i.e. you are just trying to extract some information from the innermost loop), then you can probably rewrite the entire thing using one or two simple Linq statements. If side-effects are involved, then just follow the time-tested practice of subroutines.

like image 58
Aaronaught Avatar answered Sep 17 '22 14:09

Aaronaught


You're going to have to be more specific about what you mean regarding "more elegant", as IMO there's nothing particularly inelegant about a nested foreach.

That being said, the LINQ extension methods in .NET 3.5 and above can help out (specifically 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))
{
    ...
}
like image 33
Adam Robinson Avatar answered Sep 18 '22 14:09

Adam Robinson