1. Функции, реализованные по yield
доходность дохода:
Рассмотрим следующий код, который реализует функцию, аналогичную прохождению массива с foreach через yield return, что указывает на то, что yield return также используется для реализации функции итератора.
Разрыв доходности:
Если смотреть на код ниже, выходят только 1 и 2, но не 3, что указывает на то, что итератор был остановлен из-за прорыва дохода, поэтому для завершения итерации используется прерыв доходности.
2. Его можно использовать только в <T><T>методах, операторах, получающих аксесоры, которые должны возвращать IEnumerable, IEnumerable, IEnumerator или IEnumerator.
3. Принцип реализации ключевого слова yield
Мы заменили цикл foreach на цикл while и обнаружили, что, хотя мы не реализовали GetEnumerator(), а также не реализовали соответствующие свойства MoveNext() и Current для IEnumerator, мы всё равно работали с этими функциями.
Что касается причин, мы можем использовать ILSpy для декомпиляции сгенерированного exe и поиска причины.
Поскольку прямая декомпиляция в C# станет такой, какая она есть.
Поэтому мы решили декомпилировать его в код IL с аннотациями на C#, хотя читаемость слабая, но мы можем подробно понять принципы. Давайте сначала посмотрим на перевод программы: новый класс автоматически генерируется во время компиляции.
Давайте подробнее рассмотрим код, и EnumerableFuc() возвращает этот новый класс.
Если посмотреть на реализацию класса, который этот код генерирует автоматически, мы видим, что он наследует IEnumerable<T>, IEnumerable, IEnumerator или IEnumerator, и <T>мы можем предположить, что именно этот новый класс является причиной того, почему мы не реализуем соответствующие свойства IEnumerator MoveNext() и Current, но мы всё равно можем использовать эти функции нормально.
Давайте посмотрим, как этот класс итерируется, в основном рассмотрим функцию MoveNext()
Каждый вызов функции MoveNext() добавляет 1 к состоянию, и всего выполняется 4 итерации: первые три возвращают true, а последняя — false, что означает конец итерации. Эти четыре итерации соответствуют операторам в enumberableFuc(), которые делятся на 4 части на 3, что приносит доходность.
Реальный процесс итерации с enumerableFuc() выглядит следующим образом:
1. Запустите функцию enumberableFuc(), чтобы получить экземпляр класса, автоматически сгенерированного кодом. 2. Затем вызвать функцию GetEnumberator(), чтобы начать итерацию по самому приобретённому класу в качестве итератора. 3. Каждый раз, когда вы запускаете MoveNext(), состояние увеличивается на 1, и оператор switch позволяет выполнять разные части кода при вызове MoveNext(). 4。 MoveNext() возвращает false, ending. Это также показывает, что ключевое слово yield на самом деле является синтаксическим сахаром и в конечном итоге является итеративной функцией, реализуемой с помощью <T>интерфейсов IEnumerable, IEnumerable, <T>IEnumberator и IEnumberator.
|