scohe001
scohe001

Reputation: 15446

C# Wait for function to return yield break to continue

I'm working in Unity, and I have a large script. At some point in the script, a coroutine, foo will be started. I want this coroutine to run another IEnumerator function, bar, but I don't want bar started as a coroutines. Rather, I need foo to start running, maybe yield a few times, call bar, wait until bar has finished running, and then continue running. At the moment I'm having to make bar IEnumerable to do:

void Start () {
    StartCoroutine(foo());
}

IEnumerator foo () {
    //Do something up here
    foreach (int x in bar()) {
        yield return null; //Wait for bar to yield break
    }
    //Do more stuff down here
    yield break;
}


IEnumerable bar () {
    for (int x=0; x < 5; x++) {
        //Do Something 5 Times
        yield return x;
    }
    yield break;    
}

I've been searching, but I can't find the proper way to do this. There will of course be more than 10 such "bar" functions, so I don't want to have to make a for loop every time I want to call one. How can I call the other IEnuerator functions in this way?

Upvotes: 2

Views: 6652

Answers (2)

Servy
Servy

Reputation: 203842

What you're looking for is something frequently called a yield foreach. It's a feature that doesn't exist (despite being rather frequently requested). You're pretty much forced to do exactly what you're doing here.

When you're writing an iterator block and you wish to yield each of the items of some other IEnumerable or IEnumerator individually you have no choice but to explicitly enumerate the sequence and yield each item. It would be nice if you could write something like yield foreach Bar() but you can't. Your existing solution is as good as you can get using the current language features.

Upvotes: 2

Alex
Alex

Reputation: 13224

How about something like this:

class Program
{
    public class CoroutineThing
    {
        public IEnumerator foo()
        {
            //Do something up here
            var nTimesInvoked = 0;
            while (bar(nTimesInvoked++))
                yield return null; //Wait for bar to yield break
            //Do more stuff down here
            yield break;
        }
        bool bar(int nTimesInvoked)
        {
            if (nTimesInvoked < 5)
            {
                Console.WriteLine("Bar: {0}", nTimesInvoked);
                // Do something;
            }
            return nTimesInvoked < 4;
        }
    }
    public static void Main(params string[] args)
    {
        var cor = new CoroutineThing();
        var nFoo = 0;
        var e = cor.foo();
        while (e.MoveNext())
        {
            nFoo++;
            Console.WriteLine("{0} times foo", nFoo);
        }
        Console.ReadLine();
    }
}

Upvotes: 0

Related Questions