1. Fonctions implémentées par yield
rendement :
Examinons le code suivant, qui implémente une fonction similaire à parcourir un tableau avec foreach via yield return, indiquant que yield return est également utilisé pour implémenter la fonction de l’itérateur.
Coupure de rendement :
En regardant le code ci-dessous, seuls 1 et 2 sont produits, mais pas 3, ce qui indique que l’itérateur a été arrêté par la rupture de cédement, donc la rupture de cédent est utilisée pour terminer l’itération.
2. Il ne peut être utilisé que dans <T><T>des méthodes, opérateurs, accès qui doivent retourner un IEnumerable, IEnumerable, IEnumerator ou IEnumerator.
3. Le principe de mise en œuvre du mot-clé yield
Nous avons remplacé la boucle foreach par une boucle while et constaté que, bien que nous n’ayons pas implémenté GetEnumerator(), ni les propriétés MoveNext() et Current correspondantes d’IEnumerator, nous avons tout de même travaillé avec ces fonctions.
Quant à la raison de cela, nous pouvons utiliser ILSpy pour décompiler l’exe généré afin d’en trouver la raison.
Puisque la décompilation directe en C# deviendra ce qu’elle est
Nous avons donc choisi de le décompiler en code IL avec des annotations C#, bien que la lisibilité soit faible, mais nous pouvons comprendre les principes en détail. Commençons par examiner la traduction du programme, une nouvelle classe est automatiquement générée lors de la compilation.
Examinons de plus près le code, et EnumerableFuc() renvoie cette nouvelle classe.
En regardant l’implémentation de la classe générée automatiquement par ce code, on peut voir qu’elle hérite IEnumerable<T>, IEnumerable, IEnumerator ou IEnumerator, et on <T>devrait pouvoir deviner que cette nouvelle classe est la raison pour laquelle nous n’implémentons pas les propriétés MoveNext() et Current correspondantes de l’IEnumerator, mais on peut toujours utiliser ces fonctions normalement.
Voyons comment cette classe s’itère ; regardons principalement la fonction MoveNext()
Chaque appel à la fonction MoveNext() ajoute 1 à l’état, et un total de 4 itérations sont effectuées, les trois premières retournant true et la dernière retournant false, ce qui signifie la fin de l’itération. Ces quatre itérations correspondent aux instructions dans enumberableFuc() qui sont divisées en 4 parties par 3 instructions yield.
Le véritable processus d’itération avec enumberableFuc() est :
1. Exécuter la fonction enumberableFuc() pour obtenir une instance de la classe générée automatiquement par le code. 2. Appelez ensuite la fonction GetEnumberator() pour commencer à itérer sur la classe acquise elle-même en tant qu’itérateur. 3. Chaque fois que vous exécutez MoveNext(), l’état augmente de 1, et l’instruction switch vous permet d’exécuter différentes parties du code à chaque fois que vous appelez MoveNext(). 4。 MoveNext() renvoie faux, fin. Cela montre également que le mot-clé yield est en réalité un sucre syntaxique, et qu’il s’agit finalement d’une fonction itérative implémentée par la mise en œuvre <T>des interfaces IEnumberable, IEnumberable, <T>IEnumberator et IEnumberator.
|