1. Funkcie implementované pomocou yield
Výnos:
Pozrime sa na nasledujúci kód, ktorý implementuje funkciu podobnú prechádzaniu poľom s návratom od foreach po výnos, čo naznačuje, že výnosový návrat sa používa aj na implementáciu funkcie iterátora.
Yield break:
Pri pohľade na kód nižšie sú výstupom len 1 a 2, ale nie 3, čo naznačuje, že iterátor bol zastavený yield breakom, takže yield break sa používa na ukončenie iterácie.
2. Môže sa použiť iba v <T><T>metódach, operátoroch, get accessoroch, ktoré musia vracať IEnumerable, IEnumerable, IEnumerator alebo IEnumerator.
3. Implementačný princíp kľúčového slova yield
Nahradili sme foreach slučku while slučkou a zistili sme, že hoci sme neimplementovali GetEnumerator(), ani zodpovedajúce vlastnosti MoveNext() a Current z IEnumeratora, stále sme pracovali s týmito funkciami.
Čo sa týka toho, prečo je to tak, môžeme použiť ILSpy na dekompiláciu vygenerovaného exe súboru, aby sme našli dôvod.
Keďže priama dekompilácia do C# sa stane taká, aká je
Preto sme sa rozhodli dekompilovať ho do IL kódu s C# anotáciami, hoci čitateľnosť je slabá, ale princípy dokážeme pochopiť podrobne. Najskôr sa pozrime na preklad programu, počas kompilácie sa automaticky generuje nová trieda.
Pozrime sa bližšie na kód a EnumerableFuc() vracia túto novú triedu.
Pri pohľade na implementáciu triedy, ktorú tento kód automaticky generuje, vidíme, že dedí IEnumerable<T>, IEnumerable, IEnumerator alebo IEnumerator, a <T>mali by sme byť schopní uhádnuť, že táto nová trieda je dôvodom, prečo neimplementujeme zodpovedajúce vlastnosti MoveNext() a Current zodpovedajúceho IEnumeratora, ale tieto funkcie môžeme používať normálne.
Pozrime sa, ako táto trieda iteruje, hlavne sa pozrime na funkciu MoveNext()
Každé volanie funkcie MoveNext() pridáva 1 do stavu a celkovo sa vykonávajú 4 iterácie, z ktorých prvé tri vracajú true a posledná false, čo znamená koniec iterácie. Tieto štyri iterácie zodpovedajú príkazom v enumberableFuc(), ktoré sú rozdelené do 4 častí pomocou 3 príkazov yield return.
Skutočný proces iterácie pomocou enumberableFuc() je:
1. Spustiť funkciu enumberableFuc() na získanie inštancie triedy automaticky generovanej kódom. 2. Potom zavolajte funkciu GetEnumberator(), aby ste začali iterovať na získanej triede ako iterátore. 3. Pri každom spustení MoveNext() sa stav zvýši o 1 a príkaz switch vám umožní vykonať rôzne časti kódu zakaždým, keď zavoláte MoveNext(). 4。 MoveNext() vráti false, konec. To tiež ukazuje, že kľúčové slovo yield je v skutočnosti syntaktický cukor a v konečnom dôsledku ide o iteratívnu funkciu implementovanú implementáciou rozhraní IEnumberable<T>, IEnumberable, <T>IEnumberator a IEnumberator.
|