SkunkSpinner
SkunkSpinner

Reputation: 11636

Continue in nested while loops

In this code sample, is there any way to continue on the outer loop from the catch block?

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           continue;
       }
   }
}

Upvotes: 81

Views: 79286

Answers (11)

Slipoch
Slipoch

Reputation: 785

If you wish to use try catch, simply move them outwards (although I would recommend refactoring).

I would only do this if it IS an error and needs logging, I would also push

while
{
    try 
    {
        DoStuffToThisElement(item);
    }
    catch(Exception ex)
    {
        logError(ex);
    }
}

private void  DoStuffToThisElement(Item item)
{
    while
    {
        if(condition)
        {
            throw;
        }
    }
}

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 659956

UPDATE: This question was inspiration for my article on this subject. Thanks for the great question!


"continue" and "break" are nothing more than a pleasant syntax for a "goto". Apparently by giving them cute names and restricting their usages to particular control structures, they no longer draw the ire of the "all gotos are all bad all the time" crowd.

If what you want to do is a continue-to-outer, you could simply define a label at the top of the outer loop and then "goto" that label. If you felt that doing so did not impede the comprehensibility of the code, then that might be the most expedient solution.

However, I would take this as an opportunity to consider whether your control flow would benefit from some refactoring. Whenever I have conditional "break" and "continue" in nested loops, I consider refactoring.

Consider:

successfulCandidate = null;
foreach(var candidate in candidates)
{
  foreach(var criterion in criteria)
  {
    if (!candidate.Meets(criterion))
    {  // TODO: no point in continuing checking criteria.
       // TODO: Somehow "continue" outer loop to check next candidate
    }
  }
  successfulCandidate = candidate;
  break;
}
if (successfulCandidate != null) // do something

Two refactoring techniques:

First, extract the inner loop to a method:

foreach(var candidate in candidates)
{
  if (MeetsCriteria(candidate, criteria))
  { 
      successfulCandidate = candidate;
      break;
  }
}

Second, can all the loops be eliminated? If you are looping because you are trying to search for something, then refactor it into a query.

var results = from candidate in candidates 
              where criteria.All(criterion=>candidate.Meets(criterion))
              select candidate;
var successfulCandidate = results.FirstOrDefault();
if (successfulCandidate != null)
{
  do something with the candidate
}

If there are no loops then there is no need to break or continue!

Upvotes: 126

ryansstack
ryansstack

Reputation: 1476

    while
    {
       // outer loop

       while
       {
           // inner loop
           try
           {
               throw;
           }
           catch 
           {
               // how do I continue on the outer loop from here?
               goto REPEAT;
           }
       }
       // end of outer loop
REPEAT: 
       // some statement or ; 
    }

Problem solved. (what?? Why are you all giving me that dirty look?)

Upvotes: 51

elitsa
elitsa

Reputation:

using System;

namespace Examples
{

    public class Continue : Exception { }
    public class Break : Exception { }

    public class NestedLoop
    {
        static public void ContinueOnParentLoopLevel()
        {
            while(true)
            try {
               // outer loop

               while(true)
               {
                   // inner loop

                   try
                   {
                       throw new Exception("Bali mu mamata");
                   }
                   catch (Exception)
                   {
                       // how do I continue on the outer loop from here?

                       throw new Continue();
                   }
               }
            } catch (Continue) {
                   continue;
            }
        } 
    }

}

}

Upvotes: -2

zvrba
zvrba

Reputation: 24546

Use an own exception type, e.g., MyException. Then:

while
{
   try {
   // outer loop
   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           throw MyException;
       }
   }
   } catch(MyException)
   { ; }
}

This will work for continuing and breaking out of several levels of nested while statements. Sorry for bad formatting ;)

Upvotes: -4

Maxim Zaslavsky
Maxim Zaslavsky

Reputation: 18067

I think the best way to accomplish this would be to use the break statement. Break ends the current loop and continues execution from where it ends. In this case, it would end the inner loop and jump back into the outer while loop. This is what your code would look like:

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // break jumps to outer loop, ends inner loop immediately.
           break; //THIS IS THE BREAK
       }
   }
}

I believe that is what you were looking to be accomplished, correct? Thanks!

Upvotes: -1

David Basarab
David Basarab

Reputation: 73301

You just want to break from the inner which would continue the outer.

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           break;
       }
   }
}

Upvotes: 0

Marco Mustapic
Marco Mustapic

Reputation: 3859

Use break in the inner loop.

Upvotes: 3

Jake Pearson
Jake Pearson

Reputation: 27717

You can use a break; statement.

while
{
   while
   {
       try
       {
           throw;
       }
       catch 
       {
           break;
       }
   }
}

Continue is used to jump back to the top of the current loop.

If you need to break out more levels than that you will either have to add some kind of 'if' or use the dreaded/not recommended 'goto'.

Upvotes: 22

shahkalpesh
shahkalpesh

Reputation: 33476

No.
I suggest, extracting the inner loop into a separate method.

while
{
   // outer loop
       try
       {
           myMethodWithWhileLoopThatThrowsException()
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           continue;
       }
   }
}

Upvotes: 5

Welbog
Welbog

Reputation: 60378

Swap the try/catch structure with the inner while loop:

while {
  try {
    while {
      throw;
    }
  }
  catch {
    continue;
  }
}

Upvotes: 10

Related Questions