1. Funzioni implementate tramite rendimento
Rendimento di rendimento:
Diamo un'occhiata al seguente codice, che implementa una funzione simile a attraversare un array con foreach attraverso yield return, indicando che yield return viene usato anche per implementare la funzione dell'iteratore.
Svantaggio di scossa:
Guardando il codice qui sotto, solo 1 e 2 risultano in output, ma non 3, il che indica che l'iteratore è stato fermato dal yield break, quindi il yield break viene usato per terminare l'iterazione.
2. Può essere usato solo in <T><T>metodi, operatori, access access che devono restituire un IEnumerable, IEnumerable, IEnumerator o IEnumerator.
3. Il principio di implementazione della parola chiave yield
Abbiamo sostituito il ciclo foreach con un ciclo while e abbiamo scoperto che, sebbene non abbiamo implementato GetEnumerator(), né le proprietà MoveNext() e Current di IEnumerator corrispondenti, abbiamo comunque lavorato con queste funzioni.
Per quanto riguarda il motivo, possiamo usare ILSpy per decompilare l'exe generato e trovare il motivo.
Poiché la decompilazione diretta in C# diventerà così com'è
Perciò abbiamo scelto di decompilarlo in codice IL con annotazioni C#, anche se la leggibilità è scarsa, ma possiamo comprendere i principi in dettaglio. Diamo un'occhiata prima alla traduzione del programma: durante la compilazione viene generata automaticamente una nuova classe.
Diamo un'occhiata più da vicino al codice, e EnumerableFuc() restituisce questa nuova classe.
Osservando l'implementazione della classe che questo codice genera automaticamente, possiamo vedere che eredita IEnumerable<T>, IEnumerable, IEnumerator o IEnumerator, e <T>dovremmo essere in grado di ipotizzare che questa nuova classe sia il motivo per cui non implementiamo le proprietà MoveNext() e Current di IEnumerator corrispondenti, ma possiamo comunque usare queste funzioni normalmente.
Diamo un'occhiata a come si itera questa classe, vediamo principalmente la funzione MoveNext()
Ogni chiamata alla funzione MoveNext() aggiunge 1 allo stato, e si effettuano un totale di 4 iterazioni, le prime tre restituiscono true e l'ultima returna false, il che significa la fine dell'iterazione. Queste quattro iterazioni corrispondono alle istruzioni in enumberableFuc() suddivise in 4 parti da 3 istruzioni yield return.
Il vero processo di iterazione con enumberableFuc() è:
1. Eseguire la funzione enumberableFuc() per ottenere un'istanza della classe generata automaticamente dal codice. 2. Poi chiama la funzione GetEnumberator() per iniziare a iterare sulla classe acquisita stessa come iteratore. 3. Ogni volta che esegui MoveNext(), lo stato aumenta di 1, e l'istruzione switch ti permette di eseguire parti diverse del codice ogni volta che chiami MoveNext(). 4。 MoveNext() restituisce falso, ending. Questo dimostra anche che la parola chiave yield è in realtà uno zucchero sintattico, ed è in definitiva una funzione iterativa implementata implementando <T>interfacce IEnumberable, IEnumberable, <T>IEnumberator e IEnumberator.
|