1. Funções implementadas por yield
Retorno de rendimento:
Vamos dar uma olhada no código a seguir, que implementa uma função semelhante a percorrer um array com foreach através do yield return, indicando que yield return também é usado para implementar a função do iterador.
Quebra de Rendimento:
Olhando o código abaixo, apenas 1 e 2 são gerados, mas não 3, indicando que o iterador foi parado pelo yield break, então o yield break é usado para terminar a iteração.
2. Só pode ser usado em <T><T>métodos, operadores, acessores que devem devolver um IEnumerável, IEnumerável, IEnumerador ou IEnumerador.
3. O princípio de implementação da palavra-chave yield
Substituímos o loop foreach por um loop while e descobrimos que, embora não tenhamos implementado o GetEnumerator(), nem as propriedades correspondentes MoveNext() e Current do IEnumerator, ainda trabalhamos com essas funções.
Quanto ao motivo disso, podemos usar o ILSpy para descompilar o exe gerado e encontrar o motivo.
Já que a descompilação direta para C# será como está
Por isso, optamos por descompilar para código IL com anotações em C#, embora a legibilidade seja ruim, mas conseguimos entender os princípios em detalhes. Vamos primeiro olhar para a tradução do programa, uma nova classe é gerada automaticamente durante a compilação.
Vamos analisar o código mais de perto, e EnumerableFuc() retorna essa nova classe.
Olhando para a implementação da classe que esse código gera automaticamente, podemos ver que ela herda IEnumerável<T>, IEnumerável, IEnumerator ou IEnumerator, e <T>devemos ser capazes de supor que essa nova classe é a razão pela qual não implementamos as propriedades MoveNext() e Current correspondentes do IEnumerator, mas ainda podemos usar essas funções normalmente.
Vamos dar uma olhada em como essa classe se itera, vamos principalmente olhar para a função MoveNext()
Cada chamada para a função MoveNext() adiciona 1 ao estado, e um total de 4 iterações são feitas, as três primeiras retornando true e a última retornando false, o que significa o fim da iteração. Essas quatro iterações correspondem às instruções em enumberableFuc() que são divididas em 4 partes por 3 instruções yield return.
O processo real de iterar com enumberableFuc() é:
1. Execute a função enumberableFuc() para obter uma instância da classe gerada automaticamente pelo código. 2. Depois, chame a função GetEnumberator() para começar a iterar sobre a própria classe adquirida como iterador. 3. Cada vez que você executa o MoveNext(), o estado aumenta em 1, e a instrução switch permite executar diferentes partes do código toda vez que chamar o MoveNext(). 4。 MoveNext() retorna falso, terminando. Isso também mostra que a palavra-chave yield é, na verdade, um açúcar sintático, e é, em última análise, uma função iterativa implementada por meio <T>da implementação das interfaces IEnumberable, IEnumberable, <T>IEnumberator e IEnumberator.
|