Duplicata possible :
C# - Utilisation correcte du rendement
Quel peut être un cas d'utilisation réel de C# yield ?
Gracias.
Duplicata possible :
C# - Utilisation correcte du rendement
Quel peut être un cas d'utilisation réel de C# yield ?
Gracias.
Quand vous voulez exécution différée .
Cela se justifie dans la plupart des cas où l'alternative est de construire une collection temporaire.
Considérons le scénario suivant : je dispose d'une liste d'entiers et je souhaite dresser la liste de leurs carrés.
Je pourrais le faire :
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
List<int> squares = new List<int>();
foreach (int number in numbers)
squares.Add(number * number);
return squares;
}
Je pourrais alors additionner les carrés, faire la moyenne, trouver le plus grand, etc.
Mais je n'avais vraiment pas besoin de remplir un tout nouveau fichier List<int>
à cette fin. J'aurais pu utiliser yield
pour énumérer la liste initiale et retourner les carrés un par un :
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
foreach (int number in numbers)
yield return number * number;
}
Le fait que cela fasse réellement une différence peut ne pas être apparent jusqu'à ce que vous commenciez à traiter de très grandes collections, où le fait de remplir des collections temporaires s'avère être un gaspillage important.
Supposons par exemple que je veuille trouver le premier carré au-dessus d'un certain seuil. Je pourrais le faire :
IEnumerable<int> numbers = GetLotsOfNumbers();
var squares = numbers.Squares();
int firstBigSquare = squares
.Where(x => x >= 1000)
.FirstOrDefault();
Mais si mon Squares
a peuplé tout un List<int>
avant de retourner, le code ci-dessus serait potentiellement loin plus de travail que nécessaire.
A partir de la Page MSDN sur yield
:
Utilisé dans un bloc itérateur pour fournir une valeur à l'objet énumérateur ou pour signaler la fin de l'itération.
Vous l'utilisez lorsque vous créez un itérateur personnalisé. En utilisant l'exemple de la page :
// yield-example.cs
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
En yield
signifie que le while
boucle à l'intérieur Power
se met en effet en "pause" après chaque itération pour permettre à la routine appelante d'effectuer une action. Dans ce cas, il s'agit d'imprimer le résultat.
Quand on est trop paresseux pour écrire son propre texte IEnumerator ;)
Véase cet article .
Yield agit comme un point de retour - c'est un point de retour goto non local qui préserve l'environnement de la méthode et permet au code de "sauter" en arrière. D'une manière similaire (en quelque sorte inversée) au passage d'un délégué dans une méthode qui vous permet d'injecter une logique spécifique dans une autre méthode, les fermetures vous permettent d'effectuer différents types de travail "autour" d'une méthode plus générale, ce qui vous permet de garder un code petit, modulaire et réutilisable.
Cela pourrait permettre d'obtenir un code beaucoup plus efficace. Au lieu d'instancier une très grande collection, il serait possible de permettre à des objets individuels d'être traités en séquence (et d'être éliminés après chaque opération). J'imagine qu'il est possible de construire des cas où un itérateur simple serait extrêmement difficile à construire.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.