这是实际使用的C#yield关键字 -它对www
对象没有做任何特殊的事情,而是对其包含的方法有特殊的意义。特别地,此关键字只能在返回IEnumerable
(或IEnumerator
)的方法中使用,并使用指示在调用MoveNext时枚举器将“返回”哪个对象。
之所以起作用,是因为编译器将整个方法转换为使用状态机实现IEnumerable
(或IEnumerator
)的单独类-最终结果是,直到有人通过返回值枚举时,方法本身的主体才被执行。这适用于任何类型,绝对没有什么特别的WWW
,而是它的特殊的包含方法。
看看C#yield关键字的幕后花絮,以更深入地了解C#编译器生成的是哪种代码,或者只是使用IL Spy之类的东西自己进行实验和检查代码
更新:澄清
- 当Unity调用包含一条
yield return
语句的协程时,所有发生的事情就是返回了一个枚举数-此时,方法体均未执行
- 要使方法体执行,Unity必须调用
MoveNext
迭代器才能获得序列中的第一个值。这将导致该方法执行到第一个yeild return
语句,然后调用者继续执行(大概是Unity继续渲染其余帧)
- 据我了解,Unity通常会继续调用
MoveNext
每个后续帧中一次在迭代器方法,从而导致该方法在yield return
每个帧中再次执行直到下一个语句,直到yield break
到达方法或语句的末尾(指示序列的结尾)
这里(并且在唯一的特殊位夫妇的其他情况),是团结不进这个特殊的迭代器的下一个框架,而不是只前进迭代(其方法继续执行),当下载完成。尽管似乎确实存在一个基本的YieldInstruction类,该类大概包含一个通用机制,用于在应提高迭代器时向Unity发出信号,但WWW
该类似乎没有继承自此类,因此我只能假设存在一个特殊情况Unity引擎中的此类。
请注意- yield
关键字对WWW
,而是Unity对返回的枚举的成员进行的特殊处理,从而导致这种行为。
更新第二个:至于用于WWW
异步下载网页的机制,它可能使用HttpWebRequest.BeginGetResponse方法,该方法将在内部使用异步IO,或者可以使用线程(创建专用线程或使用线程池)。
yield return
用于异步操作是一种技巧。在“真实的” C#程序中,您将Task
为此使用。Unity可能不使用它们,因为它是在Task
引入.Net 4.0之前创建的。