How does this function with a “yield” work in detail?

半世苍凉 提交于 2019-11-27 20:43:26

The Enumerator the compiler generates for you is being iterated. Once.

The compiler will generate a class that implements IEnumerator, which has a MoveNext() function and a Current property. The class will have all the members required to store the state of the function between calls. The exact details can be considered "Compiler Magic".

The object of this generated class, will be handled and managed by the Unity3d Engine. The Unity3d Engine will call MoveNext() on each active coroutine once every frame (unless instructed otherwise).

This enabled the Unity3d Programmer to write scripts that are played out one frame at a time. A combination of C# compiler magic and Unity3d Engine magic results in very-powerful-but-easy-to-use scripting.

To answer your question: the code in your function will be executed once, but it will pause at the 'yield return' statement.

As stated above, a special object that implements IEnumerator is created by the C# compiler.

On the first call to MoveNext(), your function creates an explosion and sets the current object to "new WaitForSeconds(1.5f)".

The Unity3d engine inspects this object, sees it is an instance of the special class "WaitForSeconds" so puts the enumerator on some waiting queue, and won't ask for the second element until 1.5 sec have passed. In the meantime, many frames will be rendered and the explosion will be played.

After 1.5 sec, Unity will grap the enumerator from the queue, and call MoveNext() again. The second part of your function will execute now, but will fail to generate a second object. MoveNext() will return false to indicate it failed to get a new element, which is the signal to Unity3d to throw this enumerator away. The Garbage Collector will reclaim the memory at some point in time.

As said: lots of compiler and Unity3d magic is going on. As long as you remember that your function will be put on hold till the next frame at each yield return statement, you'll know enough to benefit from those special functions.

If yield is used once, it is as if you were returning an IEnumerator with one element, that's why you get the impression that it does not iterate.

It's a rather strange use of the yield keyword, it's difficult to understand why it was implemented so without seeing the whole context.

It is better to return IEnumerable rather than IEnumerator as it is more flaxible and easy to use. It is even better to use IEnumerable<T>. Yield return is just syntactic sugar for implementing an iterator block, the compiler generates the relevent code as it is essentially standard boiler plate that can be easily generated programatically. You generally use yield return when you want to make a series of single actions apear to be a collection, e.g.:

public IEnumerable<Thing> GetThings()
{
    yield return GetNextThing();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!