1. Funktioner implementerade av yield
Avkastning:
Låt oss titta på följande kod, som implementerar en funktion liknande att traversera en array med foreach genom yield return, vilket indikerar att yield return också används för att implementera iteratorns funktion.
Viktbrytning:
Om man tittar på koden nedan finns endast 1 och 2 utmatning, men inte 3, vilket indikerar att iteratorn stoppades av yield break, så yield break används för att avsluta iterationen.
2. Den kan endast användas i <T><T>metoder, operatorer, get-accessorer som måste returnera en IEnumerable, IEnumerable, IEnumerator eller IEnumerator.
3. Implementeringsprincipen för yield-nyckelord
Vi ersatte foreach-loopen med en while-loop och upptäckte att även om vi inte implementerade GetEnumerator(), och inte heller motsvarande IEnumerators MoveNext(), och Current-egenskaper, så arbetade vi ändå med dessa funktioner.
När det gäller varför detta är fallet kan vi använda ILSpy för att dekompilera den genererade exe:n för att hitta orsaken.
Eftersom direkt dekompilering till C# kommer att bli som den är
Därför valde vi att dekompilera den till IL-kod med C#-anteckningar, även om läsbarheten är dålig, men vi kan förstå principerna i detalj. Låt oss först titta på översättningen av programmet, en ny klass genereras automatiskt under kompileringen.
Låt oss titta närmare på koden, och EnumerableFuc() returnerar denna nya klass.
Om vi tittar på implementationen av klassen som denna kod genererar automatiskt, kan vi se att den ärver IEnumerable<T>, IEnumerable, IEnumerator eller IEnumerator, och vi <T>bör kunna gissa att denna nya klass är anledningen till att vi inte implementerar motsvarande IEnumerators MoveNext() och Current-egenskaper, men vi kan fortfarande använda dessa funktioner normalt.
Låt oss titta på hur denna klass itererar, låt oss främst titta på MoveNext()-funktionen
Varje anrop till MoveNext()-funktionen lägger till 1 till tillståndet, och totalt görs 4 iterationer, där de första tre returnerar true och den sista false returnerar, vilket betyder slutet på iterationen. Dessa fyra iterationer motsvarar påståenden i enumberableFuc() som är indelade i 4 delar av 3 yield return-satser.
Den verkliga processen att iterera med enumberableFuc() är:
1. Kör funktionen enumberableFuc() för att få en instans av klassen som automatiskt genereras av koden. 2. Anropa sedan funktionen GetEnumberator() för att börja iterera på den förvärvade klassen som iterator. 3. Varje gång du kör MoveNext() ökar tillståndet med 1, och switch-satsen låter dig köra olika delar av koden varje gång du anropar MoveNext(). 4。 MoveNext() returnerar false, slut. Detta visar också att yield-nyckelordet faktiskt är ett syntaktiskt socker, och det är i slutändan en iterativ funktion som implementeras genom att implementera gränssnitt för IEnumberable<T>, IEnumberable, <T>IEnumberator och IEnumberator.
|