1. Funkcije, implementirane z yieldom
Donos:
Poglejmo si naslednjo kodo, ki implementira funkcijo, podobno prečkanju polja s foreach do yield return, kar kaže, da se yield return uporablja tudi za implementacijo funkcije iteratorja.
Yield break:
Če pogledamo spodnjo kodo, sta izhodna le 1 in 2, ne pa 3, kar kaže, da je bil iterator ustavljen zaradi preloma donosnosti, zato se prelom donosa uporablja za zaključek iteracije.
2. Uporablja se lahko le v <T><T>metodah, operatorjih, get accessorjih, ki morajo vrniti IEnumerable, IEnumerable, IEnumerator ali IEnumerator.
3. Načelo implementacije ključne besede yield
Zamenjali smo foreach zanko z while zanko in ugotovili, da čeprav nismo implementirali GetEnumerator(), prav tako nismo implementirali ustreznih lastnosti MoveNext() in Current ustreznega IEnumeratorja, smo še vedno delali s temi funkcijami.
Kar zadeva razloge za to, lahko uporabimo ILSpy za dekompilacijo generiranega exe datoteke, da najdemo razlog.
Ker bo neposredna dekompilacija v C# postala takšna, kot je
Zato smo se odločili, da ga dekompiliramo v IL kodo s C# anotacijami, čeprav je berljivost slaba, vendar lahko načela podrobno razumemo. Najprej si poglejmo prevod programa, nov razred se samodejno ustvari med prevajanjem.
Poglejmo si kodo podrobneje in EnumerableFuc() vrne ta nov razred.
Če pogledamo implementacijo razreda, ki ga ta koda generira samodejno, lahko vidimo, da podeduje IEnumerable<T>, IEnumerable, IEnumerator ali IEnumerator, in <T>morali bi ugibati, da je ta novi razred razlog, zakaj ne implementiramo ustreznih lastnosti MoveNext() in Current ustreznega IEnumeratorja, vendar lahko te funkcije še vedno uporabljamo normalno.
Poglejmo, kako ta razred iterira, poglejmo predvsem funkcijo MoveNext()
Vsak klic funkcije MoveNext() doda 1 k stanju, skupaj pa se izvedejo 4 iteracije, prve tri vrnejo true, zadnja pa false, kar pomeni konec iteracije. Te štiri iteracije ustrezajo izjavam v enumberableFuc(), ki so razdeljene na 4 dele s 3 izjavami yield return.
Pravi postopek iteracije z enumerableFuc() je:
1. Zaženite funkcijo enumberableFuc(), da dobite instanco razreda, ki ga samodejno generira koda. 2. Nato pokliči funkcijo GetEnumberator(), da začneš iterirati na pridobljenem razredu kot iteratorju. 3. Vsakič, ko zaženete MoveNext(), se stanje poveča za 1, in ukaz switch vam omogoča, da vsakič, ko pokličete MoveNext(), izvedete različne dele kode. 4。 MoveNext() vrne false, zaključek. To prav tako kaže, da je ključna beseda yield pravzaprav sintaktični sladkor in je v končni fazi iterativna funkcija, implementirana z implementacijo vmesnikov IEnumberable<T>, IEnumberable, <T>IEnumberator in IEnumberator.
|