views:

107

answers:

2

hi there!

what's the best practise to break a loop? my ideas were:

Child Find(Parent parent, object criteria)
{
    Child child = null;

    foreach(Child wannabe in parent.Childs)
    {
        if (wannabe.Match(criteria))
        {
            child = wannabe;
        }
        else
        {
            child = Find(wannabe, criteria);
        }

        if (child != null) break;
    }

    return child;
}

or

Child Find(Parent parent, object criteria)
{
    Child child = null;
    var conditionator = from c in parent.Childs where child != null select c;

    foreach(Child wannabe in conditionator)
    {
        if (wannabe.Match(criteria))
        {
            child = wannabe;
        }
        else
        {
            child = Find(wannabe, criteria);
        }
    }

    return child;
}

or

Child Find(Parent parent, object criteria)
{
    Child child = null;
    var enumerator = parent.Childs.GetEnumerator();

    while(child != null && enumerator.MoveNext())
    {
        if (enumerator.Current.Match(criteria))
        {
            child = wannabe;
        }
        else
        {
            child = Find(wannabe, criteria);
        }
    }

    return child;
}

what do u think, any better ideas? i'm looking for the niciest solution :D

mo

+1  A: 

There's no need for you to deal with the IEnumerator yourself, so option 3 is out.

Option 2 does not function. It continues regardless of finding a match, and if the last child is not a match and its children do not contain a match, then the result will be null even if there was a prior match.

Option 1 seems the cleanest, assuming you object to multiple return statements.

Adam Robinson
u are right :) i see the mistake.
mo
Downvoter care to comment why?
Adam Robinson
@mo: The issue is still there with option 2.
Adam Robinson
Option 1 has a problem that it will continue to recursively search for a match in the other children even when it has already found one.
Ants
@Ants: No, it won't; option 2 will do that, not option 1.
Adam Robinson
i didnt see my fault @ 2.the linq-expr. breaks if child != null.so the foreach will break.i'm blind!
mo
Somebody did an edit after I posted. That "if (child != null) break;" line was not there originally in option 1. The "break" used to be in the success clause.
Ants
I agree with Adam about 1 being the cleanest (I would have been stronger and said only IF you use return statements). As an aside,I do not get why people down vote here without any explanation, and SO should automatically down vote anonymous down voters who ddon't explain themselves, IMO. Cheers
Berryl
+8  A: 

Linq may be more terse, but can be more difficult to understand!

    Child Find(Parent parent, object criteria)
    {
        return parent.Childs.Select(        // Loop through the children looking for those that match the following criteria
            c => c.Match(criteria)          // Does this child match the criteria?
                ? c                         // If so, just return this child
                : this.Find(c, criteria)    // If not, try to find it in this child's children
        ).FirstOrDefault();                 // We're only interested in the first child that matches the criteria or null if none found
    }
Daniel Renshaw
that works? i'm testing it.it looks great :)
mo
seems to work :)
mo
@mo LOL! You don't like the multiple return statements on the claim that it's hard to debug, but this is acceptable? Try stepping through with a debugger and see which you'll prefer a few months from now when the code isn't fresh in your mind. :-)
Ants
this is really a cool solution.but some devs in my team will never understand it :) for them it is hard to understand.
mo
it has one return :). the debugging issue still exist
mo
it is hard to understand (for unexp. devs).but for a simple recursive search it will do the job.(it is not debuggable) :)
mo