nr: #2 dodano: 2017-01-04 02:01
You are right that yield and await are closely related. Both are points in a workflow where the current method is paused, control is returned to the caller, and the method resumes at an unspecified point in the future at the point where the yield / await happened.
But they are very different in terms of their action on their operands. They are in fact duals of each other. A yield provides a new value when demanded by the code iterating the sequence. An await extracts a value when it is produced by the asynchronously executing task.
Null is a perfectly valid value, so it makes sense for a yield to proffer it up to its caller. But null is not a valid task, and so it makes no sense for await to attempt to extract the value from the task.
Currently in Unity3d you can yield return null; inside a coroutine to represent "Wait for next frame".
In an async-await asynchronous workflow the analog of
yield return null; is just
return null;. That means "end this portion of the asynchronous workflow by providing the null reference". Why are you not simply returning null if you intend to produce a task whose result is null?
Let me put it another way that might be more clear. Obviously this makes no sense:
foreach(var x in null)
This is identically nonsensical:
var x = await null;
These are the same thing logically. Foreach means "extract a value from the sequence as long as values are available", but null is not a sequence. Similarly, "await" means "extract a value from the task as soon as a value is available", but null is not a task.
That's the key: the asynchronous analog of
await is not
yield return, it's
foreach. That's the mechanism that extracts the
T from the
Task<T>. The thing that puts the
T into the monadic type is
yield return for