1. Функції, реалізовані за доходністю
Доходність:
Розглянемо наступний код, який реалізує функцію, подібну до проходження масиву з 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() повертає цей новий клас.
Дивлячись на реалізацію класу, який цей код генерує автоматично, ми бачимо, що він успадковує <T>IEnumerable, 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, закінчується. Це також показує, що ключове слово yield насправді є синтаксичним цукрам, і врешті-решт це ітеративна функція, реалізована шляхом реалізації <T>інтерфейсів IEnumerable, IEnumerable, <T>IEnumberator та IEnumberator.
|