Это ключевое слово 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был представлен.