Recipe 6.8. Forcing an Iterator to Stop IteratingProblemYou have a requirement that if an iterator encounters malformed or out-of-bounds data that the iterations are to stop immediately. SolutionIt is possible to throw an exception from an iterator, which terminates the iterator and the foreach loop. However, there is a more performance-friendly technique. You can use the yield break statement within your iterator: public class Foo { private List<T> _items = new List<T>(); public IEnumerator GetEnumerator() { for (int index = 0; index < _items.Count; index++) { if (/*perform some test on the data here*/) { // There was a problem with the data, stop. yield break; } else { // The data was fine, continue. yield return (_items[index]); } } } } DiscussionIt is possible to stop iterations using a throw statement to throw an exception. However, you cannot place a catch block within an iterator body to handle the thrown exception. The TRy/catch block must be around the foreach loop as shown here: Foo test = new Foo(); // Add elements to the test class… try { foreach ( object o in test) {…} } catch (Exception e) { // Handle exception from iterator method here… Console.WriteLine("In outer finally block"); } When an exception occurs inside the foreach block, the following string will be displayed: In outer finally block For more on how iterators deal with exceptions, see Recipe 6.9. Another way of terminating an iterator, and thus terminating the foreach loop, is to use the yield break statement. This statement has the same effect as simply exiting from the function. This yield break statement can be used only within an iterator block. This means any method, property get accessor, or operator overload member that is set up as an iterator (i.e., is public and returns an IEnumerable or IEnumerable<T> type). See AlsoSee Recipe 6.9; see the "Iterators," "yield," "IEnumerator Interface," and "IEnumerable Interface" topics in the MSDN documentation. |