1. Functies geïmplementeerd door yield
Rendement:
Laten we eens kijken naar de volgende code, die een functie implementeert die lijkt op het doorlopen van een array met foreach tot yield return, waarmee wordt aangegeven dat yield return ook wordt gebruikt om de functie van de iterator te implementeren.
Yield break:
Als je naar de onderstaande code kijkt, worden alleen 1 en 2 uitgevoerd, maar niet 3, wat aangeeft dat de iterator werd gestopt door yield break, dus yield break wordt gebruikt om de iteratie te beëindigen.
2. Het kan alleen worden gebruikt in <T><T>methoden, operators, get accessors die een IEnumerable, IEnumerable, IEnumerator of IEnumerator moeten teruggeven.
3. Het implementatieprincipe van yield keyword
We hebben de foreach-lus vervangen door een while-lus en ontdekten dat, hoewel we GetEnumerator() niet hebben geïmplementeerd, noch de bijbehorende IEnumerator's MoveNext(), en Current-eigenschappen, we toch met deze functies werkten.
Wat betreft waarom dit zo is, kunnen we ILSpy gebruiken om de gegenereerde exe te decompileren om de reden te vinden.
Aangezien directe decompilatie naar C# zal worden zoals het is
Daarom hebben we ervoor gekozen het te decompileren naar IL-code met C#-annotaties, hoewel de leesbaarheid slecht is, maar we de principes in detail kunnen begrijpen. Laten we eerst kijken naar de vertaling van het programma: er wordt automatisch een nieuwe klasse gegenereerd tijdens de compilatie.
Laten we de code eens nader bekijken, en EnumerableFuc() geeft deze nieuwe klasse terug.
Als we kijken naar de implementatie van de klasse die deze code automatisch genereert, zien we dat deze IEnumerable<T>, IEnumerable, IEnumerator of IEnumerator erft, en we <T>zouden moeten kunnen raden dat deze nieuwe klasse de reden is waarom we de bijbehorende MoveNext()- en Current-eigenschappen van de IEnumerator niet implementeren, maar we kunnen deze functies nog steeds normaal gebruiken.
Laten we eens kijken hoe deze klasse iterert, laten we vooral kijken naar de MoveNext()-functie
Elke aanroep van de MoveNext()-functie voegt 1 toe aan de toestand, en in totaal worden er 4 iteraties uitgevoerd, waarbij de eerste drie true teruggeven en de laatste false returns, wat het einde van de iteratie betekent. Deze vier iteraties komen overeen met de uitspraken in enumberableFuc() die zijn verdeeld in 4 delen door 3 yield return-instructies.
Het echte proces van itereren met enumberableFuc() is:
1. Voer de enumberableFuc()-functie uit om een instantie van de klasse te krijgen die automatisch door de code wordt gegenereerd. 2. Roep vervolgens de GetEnumberator()-functie aan om te beginnen met itereren op de verkregen klasse zelf als iterator. 3. Elke keer dat je MoveNext() uitvoert, neemt de status toe met 1, en de switch-instructie stelt je in staat om verschillende delen van de code uit te voeren telkens als je MoveNext() aanroept. 4。 MoveNext() geeft false terug, eindigend. Dit toont ook aan dat het yield-keyword eigenlijk een syntactische suiker is, en uiteindelijk een iteratieve functie is die wordt geïmplementeerd door IEnumberable<T>, IEnumberable, <T>IEnumberator en IEnumberator interfaces te implementeren.
|