1. Funkce implementované pomocí yield
Výnos:
Podívejme se na následující kód, který implementuje funkci podobnou procházení pole s návratem od foreach po výnos, což naznačuje, že výnosový návrat se také používá k implementaci funkce iterátoru.
Yield break:
Při pohledu na níže uvedený kód jsou výstupy pouze 1 a 2, ale ne 3, což znamená, že iterátor byl zastaven zlomem výnosu, takže zlom výnosu se používá k ukončení iterace.
2. Lze jej použít pouze v <T><T>metodách, operátorech a accessory, které musí vracet IEnumerable, IEnumerable, IEnumerator nebo IEnumerator.
3. Princip implementace klíčového slova yield
Nahradili jsme foreach smyčku smyčkou while a zjistili jsme, že i když jsme neimplementovali GetEnumerator(), ani odpovídající vlastnosti MoveNext() a Current odpovídajícího IEnumeratoru, stále jsme pracovali s těmito funkcemi.
Co se týče toho, proč tomu tak je, můžeme použít ILSpy k dekompilaci vygenerovaného exe souboru a najít důvod.
Protože přímá dekompilace do C# se stane takový, jaký je
Proto jsme se rozhodli jej dekompilovat do IL kódu s C# anotacemi, i když je čitelnost špatná, principy můžeme pochopit do detailů. Nejprve se podívejme na překlad programu, během kompilace se automaticky generuje nová třída.
Podívejme se blíže na kód a EnumerableFuc() vrací tuto novou třídu.
Při pohledu na implementaci třídy, kterou tento kód automaticky generuje, vidíme, že dědí <T>IEnumerable, IEnumerable, IEnumerator nebo IEnumerator, a <T>měli bychom být schopni odhadnout, že právě tato nová třída je důvodem, proč neimplementujeme odpovídající vlastnosti MoveNext() a Current odpovídajícího IEnumeratoru, ale tyto funkce můžeme používat normálně.
Podívejme se, jak tato třída iteruje, hlavně se zaměřme na funkci MoveNext()
Každé volání funkce MoveNext() přidá 1 ke stavu a celkem se provedou 4 iterace, první tři vrátí true a poslední false, což znamená konec iterace. Tyto čtyři iterace odpovídají příkazům v enumberableFuc(), které jsou rozděleny do 4 částí pomocí 3 yield return příkazů.
Skutečný proces iterace pomocí enumberableFuc() je:
1. Spusť funkci enumberableFuc() pro získání instance třídy automaticky generované kódem. 2. Poté zavolejte funkci GetEnumberator(), abyste začali iterovat na získané třídě jako iterátoru. 3. Pokaždé, když spustíte MoveNext(), stav se zvýší o 1 a příkaz switch vám umožní vykonat různé části kódu pokaždé, když zavoláte MoveNext(). 4。 MoveNext() vrací false, končí. To také ukazuje, že klíčové slovo yield je ve skutečnosti syntaktický cukr a je nakonec iterativní funkcí implementovanou implementací rozhraní IEnumberable<T>, IEnumberable, <T>IEnumberator a IEnumberator.
|