Question

Je sais ce que yield le fait, et j'ai vu quelques exemples, mais je n'arrive pas à penser à des applications réelles, l'avez-vous utilisé pour résoudre un problème spécifique ?

(Idéalement, un problème qui ne peut pas être résolu autrement)

Était-ce utile?

La solution

Je me rends compte que c'est une vieille question (avant Jon Skeet ?) mais j'ai moi-même réfléchi à cette question récemment.Malheureusement, les réponses actuelles ici (à mon avis) ne mentionnent pas l'avantage le plus évident de la déclaration de rendement.

Le plus grand avantage de l'instruction rendement est qu'elle vous permet de parcourir de très grandes listes avec une utilisation de la mémoire beaucoup plus efficace qu'en utilisant, par exemple, une liste standard.

Par exemple, disons que vous disposez d'une requête de base de données qui renvoie 1 million de lignes.Vous pouvez récupérer toutes les lignes à l'aide d'un DataReader et les stocker dans une liste, nécessitant donc list_size * row_size octets de mémoire.

Ou vous pouvez utiliser l'instruction rendement pour créer un itérateur et ne stocker qu'une seule ligne en mémoire à la fois.En effet, cela vous donne la possibilité de fournir une fonctionnalité de « streaming » sur de grands ensembles de données.

De plus, dans le code qui utilise l'Iterator, vous utilisez une simple boucle foreach et pouvez décider de sortir de la boucle si nécessaire.Si vous faites une pause plus tôt, vous n'avez pas forcé la récupération de l'ensemble des données alors que vous n'aviez besoin que des 5 premières lignes (par exemple).

Concernant:

Ideally some problem that cannot be solved some other way

L'instruction rendement ne vous donne rien que vous ne pourriez faire en utilisant votre propre implémentation d'itérateur personnalisé, mais elle vous évite d'avoir à écrire le code souvent complexe nécessaire.Il y a très peu de problèmes (le cas échéant) qui ne peuvent être résolus de plusieurs manières.

Voici quelques questions et réponses plus récentes qui fournissent plus de détails :

Rendement à valeur ajoutée des mots clés ?

Le rendement est-il utile en dehors de LINQ ?

Autres conseils

en fait je l'utilise de manière non traditionnelle sur mon site IdéePipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

donc fondamentalement, il vérifie si la visualisation de l'idée est actuellement autorisée et si c'est le cas, il renvoie l'idée.Si ce n'est pas le cas, il est simplement ignoré.Cela me permet de mettre en cache les idées tout en les affichant aux utilisateurs autorisés.Sinon, je devrais les extraire à chaque fois en fonction des autorisations, alors qu'ils ne sont reclassés que toutes les heures.

Une utilisation intéressante est celle d'un mécanisme de programmation asynchrone, en particulier pour les tâches qui nécessitent plusieurs étapes et nécessitent le même ensemble de données à chaque étape.Deux exemples de ceci seraient Jeffery Richters AysncEnumerator Partie 1 et Partie 2.Le Concurrency and Coordination Runtime (CCR) utilise également cette technique Itérateurs CCR.

Les opérateurs de LINQ sur la classe Enumerable sont implémentés en tant qu'itérateurs créés avec l'instruction rendement.Il vous permet d'enchaîner des opérations comme Select() et Where() sans rien énumérer jusqu'à ce que vous utilisiez réellement l'énumérateur dans une boucle, généralement en utilisant le pour chaque déclaration.De plus, étant donné qu'une seule valeur est calculée lorsque vous appelez IEnumerator.MoveNext() si vous décidez d'arrêter la collecte en cours, vous économiserez l'impact sur les performances du calcul de tous les résultats.

Les itérateurs peuvent également être utilisés pour implémenter d'autres types d'évaluation paresseuse où les expressions sont évaluées uniquement lorsque vous en avez besoin.Vous pouvez aussi utiliser rendement pour des trucs plus sophistiqués comme les coroutines.

Une autre bonne utilisation de rendement est d'exécuter une fonction sur les éléments d'un IEnumerable et de renvoyer un résultat d'un type différent, par exemple :

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}

L'utilisation du rendement peut empêcher la conversion vers un type de béton.C'est pratique pour garantir que le consommateur de la collection ne la manipule pas.

Vous pouvez aussi utiliser yield return pour traiter une série de résultats de fonction comme une liste.Prenons par exemple une entreprise qui paie ses employés toutes les deux semaines.On pourrait récupérer un sous-ensemble de dates de paie sous forme de liste en utilisant ce code :

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top