Это ключевое слово yield C # в действии - оно не делает ничего особенного с 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
будет достигнут конец метода или оператора (указывая конец последовательности)
Единственный специальный бит здесь (и в нескольких из других случаев ) является то , что Unity не продвигает эту конкретную итератор следующего кадра, вместо этого он продвигает только итератор (вызвавший метод для продолжения выполнения) , когда загрузка завершена. Хотя, похоже, есть базовая YieldInstruction класс который, предположительно, содержит общий механизм для сигнализации Unity, когда итератор должен быть расширен, WWW
класс не наследуется от этого класса, поэтому я могу только предположить, что существует особый случай для этот класс в движке Unity.
Просто чтобы прояснить: yield
ключевое слово не делает ничего особенного для WWW
класса, скорее его специальная обработка, которую Unity предоставляет членам возвращаемого перечисления, вызывает такое поведение.
Обновите второе: что касается механизма, который WWW
использует для загрузки веб-страниц асинхронно, он, вероятно, использует либо метод HttpWebRequest.BeginGetResponse, который будет внутренне использовать асинхронный ввод-вывод, либо, альтернативно, он мог бы использовать потоки (либо создавая выделенный поток, либо используя пул потоков).
yield return
для асинхронных операций является взломом. В «настоящей» C # -программе вы бы использовалиTask
для этого. Unity, вероятно, не использует их, потому что он был создан до .Net 4.0, когда онTask
был представлен.