Après presque 4 ans d'expérience, je n'ai pas vu de code dans lequel le mot clé rendement est utilisé. Quelqu'un peut-il me montrer une utilisation pratique (accompagnée d'une explication) de ce mot clé et, dans l'affirmative, n'y a-t-il pas d'autres moyens plus faciles de remplir ce qu'il peut faire?
76
yield
plutôt de savoir ce qui peut être utilisé en général.Réponses:
Efficacité
Le
yield
mot clé crée effectivement une énumération paresseuse sur les éléments de collection qui peuvent être beaucoup plus efficaces. Par exemple, si votreforeach
boucle effectue une itération sur les 5 premiers éléments de 1 million d'éléments, tout estyield
renvoyé et vous n'avez pas constitué une collection d'un million d'éléments en interne. De même , vous voulez utiliseryield
avec desIEnumerable<T>
valeurs de retour dans vos propres scénarios de programmation pour atteindre les mêmes gains d' efficience.Exemple d'efficacité gagnée dans un certain scénario
Pas une méthode itérateur, utilisation potentiellement inefficace d'une grande collection
(la collection intermédiaire est construite avec beaucoup d'articles)
Version itérateur, efficace
(aucune collection intermédiaire n'est construite)
Simplifier certains scénarios de programmation
Dans un autre cas, il est plus facile de programmer certaines sortes de tri et de fusion de listes car il vous suffit de
yield
remettre les éléments dans l'ordre souhaité plutôt que de les trier dans une collection intermédiaire et de les échanger. Il existe de nombreux scénarios de ce type.Un seul exemple est la fusion de deux listes:
Cette méthode renvoie une liste d'éléments contigus, une fusion sans aucune collection intermédiaire.
Plus d'informations
Le
yield
mot - clé ne peut être utilisé dans le contexte d'un procédé d'itération (ayant un type de retourIEnumerable
,IEnumerator
,IEnumerable<T>
, ouIEnumerator<T>
.) Et il existe une relation particulière avecforeach
. Les itérateurs sont des méthodes spéciales. La documentation sur le rendement MSDN et la documentation sur les itérateurs contiennent de nombreuses informations et explications intéressantes sur les concepts. Assurez-vous de le corréler avec leforeach
mot - clé en lisant à ce sujet également, afin de compléter votre compréhension des itérateurs.Pour savoir comment les itérateurs atteignent leur efficacité, le secret réside dans le code IL généré par le compilateur C #. L'IL généré pour une méthode itérateur diffère radicalement de celui généré pour une méthode régulière (sans itérateur). Cet article (Qu'est-ce que le mot-clé Yield génère-t-il vraiment?) Fournit ce type d'informations.
la source
database.Customers.Count()
énumération de l' énumération de tous les clients ne nécessite- t-elle pas le code le plus efficace pour parcourir chaque élément?Il y a quelque temps, j'ai eu un exemple pratique. Supposons que vous ayez une situation comme celle-ci:
L'objet bouton ne connaît pas sa propre position dans la collection. La même limitation s'applique à
Dictionary<T>
ou à d'autres types de collections.Voici ma solution en utilisant le
yield
mot-clé:Et c'est comme ça que je l'utilise:
Je n'ai pas besoin de faire une
for
boucle sur ma collection pour trouver l'index. My Button a un identifiant qui est également utilisé comme indexIndexerList<T>
pour éviter tout identifiant ou index redondant - c’est ce que j’aime! L'index / Id peut être un nombre arbitraire.la source
Un exemple pratique peut être trouvé ici:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html
L'utilisation du rendement par rapport au code standard présente plusieurs avantages:
Cependant, comme Jan_V l'a dit (il suffit de me battre de quelques secondes :-) vous pouvez vous en passer, car en interne, le compilateur produira un code presque identique dans les deux cas.
la source
Voici un exemple:
https://bitbucket.org/ant512/workingweek/src/a745d02ba16f/source/WorkingWeek/Week.cs#cl-158
La classe effectue des calculs de date basés sur une semaine de travail. Je peux dire à un exemple de la classe que Bob travaille de 9h30 à 17h30 chaque jour de la semaine avec une heure de pause pour le déjeuner à 12h30. Avec cette connaissance, la fonction AscendingShifts () générera des objets de travail par quart de travail entre les dates fournies. Pour lister tous les quarts de travail de Bob entre le 1er janvier et le 1er février de cette année, vous l'utiliseriez comme ceci:
La classe ne parcourt pas vraiment une collection. Cependant, les décalages entre deux dates peuvent être considérés comme une collection. L'
yield
opérateur permet de parcourir cette collection imaginée sans créer la collection elle-même.la source
J'ai une petite couche de données de base de données qui a une
command
classe dans laquelle vous définissez le texte de la commande SQL, le type de commande et renvoyez un IEnumerable de 'paramètres de commande'.En gros, l’idée est d’avoir des commandes CLR tapées au lieu de saisir manuellement les
SqlCommand
propriétés et les paramètres tout le temps.Donc, il y a une fonction qui ressemble à ceci:
La classe qui hérite de cette
command
classe a les propriétésAge
etName
.Ensuite, vous pouvez créer un
command
objet rempli de ses propriétés et le transmettre à unedb
interface qui effectue l'appel de commande.Globalement, il est très facile de travailler avec des commandes SQL et de les conserver typées.
la source
Bien que le cas de fusion ait déjà été traité dans la réponse acceptée, permettez-moi de vous montrer la méthode d'extension TM:
J'utilise ceci pour construire des paquets d'un protocole réseau:
La
MarkChecksum
méthode, par exemple, ressemble à ceci. Et il y ayield
aussi:Mais soyez prudent lorsque vous utilisez des méthodes d'agrégation telles que Sum () dans une méthode d'énumération, car elles déclenchent un processus d'énumération distinct.
la source
Elastic Search .NET exemple. Repo a un excellent exemple d’utilisation de
yield return
de la partition d'une collection en plusieurs collections d'une taille donnée:https://github.com/elastic/elasticsearch-net-example/blob/master/src/NuSearch.Domain/Extensions/PartitionExtension.cs
la source
En développant la réponse de Jan_V, je viens de citer un cas concret qui le concerne:
J'avais besoin d'utiliser les versions Kernel32 de FindFirstFile / FindNextFile. Vous obtenez un descripteur du premier appel et le transmettez à tous les appels suivants. Enveloppez cela dans un énumérateur et vous obtiendrez quelque chose que vous pouvez utiliser directement avec foreach.
la source