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 votre foreach
boucle effectue une itération sur les 5 premiers éléments de 1 million d'éléments, tout est yield
renvoyé et vous n'avez pas constitué une collection d'un million d'éléments en interne. De même , vous voulez utiliser yield
avec des IEnumerable<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)
// Method returns all million items before anything can loop over them.
List<object> GetAllItems() {
List<object> millionCustomers;
database.LoadMillionCustomerRecords(millionCustomers);
return millionCustomers;
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems()) {
num++;
if (num == 5)
break;
}
// Note: One million items returned, but only 5 used.
Version itérateur, efficace
(aucune collection intermédiaire n'est construite)
// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
for (int i; i < database.Customers.Count(); ++i)
yield return database.Customers[i];
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems()) {
num++;
if (num == 5)
break;
}
// Note: Only 5 items were yielded and used out of the million.
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:
IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
foreach(var o in list1)
yield return o;
foreach(var o in list2)
yield return o;
}
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 retour IEnumerable
, IEnumerator
, IEnumerable<T>
, ou IEnumerator<T>
.) Et il existe une relation particulière avec foreach
. 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 le foreach
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.