C# Why are some of these methods using delegates and generics not starting?

I was trying to learn a bit about generics and the SelectMany function and delegates. The semantic function of the code below(as in what the functions are supposed to be doing), doesn't matter. Most of them do nothing meaningful and are just attempts to see if the issue of the function not starting, persists.

That's my question.. Why is it that the method named _SelectManyIteratora doesn't start. Nor does _SelectManyIteratorb. But _SelectManyIteratorc does start.

As in, i'm calling the function, i'm not getting any compilation error, and the first line of the function, a simple WriteLine statement, is not executing!

I would have expected them all to start.

My interest is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Collections;


namespace functionwontstart
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] arrstr1 = { "abc", "def", "ghi" };
            string[] arrstr2= {"qrs","tuv","wxy"};

            _SelectManyIteratora(arrstr1, x => arrstr2, (s1, s2) => s1 + s2);
            _SelectManyIteratorb(arrstr1, x => arrstr2, (s1, s2) => s1 + s2);
           _SelectManyIteratorc(arrstr1, x => arrstr2);
            Console.ReadLine();
        }


        static IEnumerable<TResult> _SelectManyIteratora<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
        {
            Console.Write("got this far"); // no!

            foreach (TSource element in source)
                foreach (TCollection subElement in collectionSelector(element))
                    yield return resultSelector(element, subElement);                
        }

        static IEnumerable<TResult> _SelectManyIteratorb<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
        {
            Console.Write("got this far"); // no!

            TSource ts = source.ElementAt(0);
            TCollection tc = collectionSelector(ts).ElementAt(0);
            yield return resultSelector(ts, tc);
        }

        static IEnumerable<int> _SelectManyIteratorc<TSource, TCollection>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector)
        {
            Console.Write("got this far"); // yes

            return new List<int>();
        }

      } //class



} //namespace
Jon Skeet
people
quotationmark

Those methods are iterators - they use yield return. They execute in a special way... the code only gets executed as you iterate over the result.

So if you change the calling code to:

foreach (var item in _SelectManyIteratora) { }

then you'll see the method being executed. Until you start iterating over the return value, none of the code in the method executes. Each time the code hits a yield return statement, control will return to the code that's iterating over it, until that code asks for the next item - at which point it will jump back into the method, just after the yield return statement, with all the local variables in the same state as they were before.

For more details:

people

See more on this question at Stackoverflow