Esta es la palabra clave de rendimiento de C # en acción: no está haciendo nada especial con el www
objeto, sino que significa algo especial para el método que contiene. Específicamente, esta palabra clave solo se puede usar en un método que devuelve un IEnumerable
(o IEnumerator
), y se usa para indicar qué objeto será "devuelto" por el enumerador cuando se invoca MoveNext .
Funciona porque el compilador convierte todo el método en una clase separada que implementa IEnumerable
(o IEnumerator
) usando una máquina de estado; el resultado neto es que el cuerpo del método en sí no se ejecuta hasta que alguien enumera a través del valor de retorno. Esto funcionará con cualquier tipo, no tiene absolutamente nada de especial WWW
, sino que es el método que lo contiene lo que es especial.
Eche un vistazo a Detrás de escena de la palabra clave de rendimiento de C # para obtener más información sobre qué tipo de código genera el compilador de C #, o simplemente experimente e inspeccione el código usted mismo usando algo como IL Spy
Actualización: para aclarar
- Cuando Unity llama a una rutina que contiene una
yield return
declaración, todo lo que sucede es que se devuelve un enumerador; en este punto, no se ejecuta ninguno de los cuerpos del método
- Para que el cuerpo del método se ejecute, Unity debe llamar
MoveNext
al iterador para obtener el primer valor en la secuencia. Esto hace que el método se ejecute hasta la primera yeild return
instrucción, momento en el que se reanuda la llamada (y presumiblemente Unity continúa para representar el resto del marco)
- Según tengo entendido, Unity normalmente llama al
MoveNext
método en el iterador una vez por cada cuadro posterior, lo que hace que el método se ejecute nuevamente hasta la siguiente yield return
declaración una vez por cada cuadro, hasta yield break
que se alcanza el final del método o una declaración (lo que indica el final de la secuencia)
El único bit especial aquí (y en un par de otros casos ) es que Unity no avanza este iterador en particular el siguiente fotograma, sino que solo avanza el iterador (haciendo que el método continúe ejecutándose) cuando se completa la descarga. Aunque parece haber una clase YieldInstruction base que presumiblemente contiene un mecanismo genérico para indicar a Unity cuándo se debe avanzar un iterador, la WWW
clase no parece heredar de esta clase, por lo que solo puedo suponer que hay un caso especial para Esta clase en el motor de Unity.
Para ser claros, la yield
palabra clave no hace nada especial para la WWW
clase, sino que es el manejo especial que Unity le da a los miembros de la enumeración devuelta lo que causa este comportamiento.
Actualiza el segundo: cuanto al mecanismo que WWW
usa para descargar páginas web de forma asincrónica, probablemente use el método HttpWebRequest.BeginGetResponse que usará internamente IO asincrónico o, alternativamente, podría usar hilos (ya sea creando un hilo dedicado o usando un grupo de hilos).
yield return
para operaciones asincrónicas es un hack. En un programa "real" de C #, usaría unTask
para esto. Es probable que Unity no los use porque se creó antes de .Net 4.0, cuandoTask
se introdujo.