#1,193 – yield Statement and try/catch Blocks

The yield return statement is used when defining an iterator to generate the next element within a sequence (IEnumerable).  You cannot include a yield return statement in any of the following places:

  • within a try block that has a catch clause
  • within a catch block
  • within a finally block

You can include a yield return statement within a try block that only has a finally block.

        private static IEnumerable<int> IntsAndTheirDoubles()
        {
            for (int i = 1; i <= 5; i++ )
            {
                yield return i;
                try
                {
                    // Error: Cannot yield a value in the body of a try block
                    //   with a catch clause
                    yield return 2 * i;
                }
                catch (Exception xx)
                {
                    Console.WriteLine("Uh-oh");
                }
            }
        }
Advertisement

#1,118 – foreach Works with Iterator Returned by yield

You can use the yield keyword in a method to implement an iterator.  The method in which it is defined returns an IEnumerable or IEnumerator.  The resulting iterator can be consumed using the foreach statement.

Below is an example of a method that returns an IEnumerable<T> which can then be iterated upon using a foreach statement.

        static IEnumerable<Dog> DogsWithKids(IEnumerable<Dog> dogList)
        {
            foreach (Dog d in dogList)
            {
                yield return d;
                yield return new Dog(d.Name + " Jr.",
                                     Math.Max(d.Age - 3, 1));
            }
        }

        static void Main(string[] args)
        {
            List<Dog> myDogs = new List<Dog>
                {
                    new Dog {Name = "Kirby", Age = 15},
                    new Dog {Name = "Ruby", Age = 2}
                };

            // Iterate through dogs w/offsprings
            foreach (Dog d in DogsWithKids(myDogs))
                Console.WriteLine(d);

            Console.ReadLine();
        }

The result is a sequence with twice as many elements as the original List<T>.

1118-001

#561 – Using a yield break Statement

When implementing an iteratorthe yield return statement returns the next element in the sequence being returned.  If you are using a loop within the iterator block, you can use the yield break statement to break out of the loop, indicating that no more elements are to be returned.

In the example below, an iterator is used to return a portion of the Fibonacci sequence.  yield break is used to break out of the loop generating the sequence.

        static void Main()
        {
            // Return Fibonacci numbers below 2,000
            foreach (int i in Fibonacci(2000))
                Console.WriteLine(i);

            int gi = 12;
        }

        private static IEnumerable<int> Fibonacci(int maxValue)
        {
            yield return 0;
            yield return 1;

            int last = 0;
            int current = 1;

            while (true)
            {
                int next = last + current;
                if (next > maxValue)
                    yield break;
                else
                {
                    yield return next;
                    last = current;
                    current = next;
                }
            }
        }