Edited the original question to elaborate: I'm using unity coroutines to perform some heavy duty operations. Unity is a game engine and codes are run within frames. If an operation is intensive, it has to be done in coroutines otherwise it takes a long time for a frame to complete. Here the coroutine method is DoTasks
. If you are not familiar with the unity engine, they are similar to iterators.
First of all I have to say these codes work as they are supposed to do. The problem is with heap allocation. That said I will explain what the codes do. When Init
is called it starts the coroutine and goes into DoTask
and then goes inside foreach
to iterate currentTask.Execute()
and then goes into obj.CreateCellGosTask
to iterate. now the first yield return we encounter, the chain of foreachs return the result to the initial coroutine(namely StartCoroutine(DoTasks()) ) and we're done for the frame. On next frame the code continues in the chain right after the last line that was executed. This is the behaviour and works fine.
public class TaskScheduler : MonoBehaviour
{
private static volatile Task currentTask;
public void Init(){
StartCoroutine(DoTasks()); //Starts the coroutine
}
private IEnumerator DoTasks()
{
while(true){
foreach (object b in currentTask.Execute())
{
yield return b;
//Do something
}
}
}
public class Task
{
private Cell cell;
public IEnumerable Execute()
{
foreach (object b in cell.CreateCellGosTask()){
yield return b;
// Do something
}
}
What the yield returns is of zero importance. In all nested iterators it yield returns null.
The problem is about heap allocation. The code creates garbage due to the fact that the compiler generates hidden classes implementing IEnumerable (I think). Unfortunately Garbage collection is a big deal in unity.
The ultimate goal is to zero heap allocation in foreach chain (StartCoroutine is not important).So the question is exactly what code the compiler generates and How it creates Enumerable and Enumerator classes? I mean the exact generated code of DoTasks
and Execute
. Then I could just type the exact same code and create and return a struct instead of a class.