Eric Lippert soulève un bon point (dommage que le C# ne dispose pas de aplatissement du flux comme Cw ). J'ajouterais que parfois le processus d'énumération est coûteux pour d'autres raisons, et que vous devriez donc utiliser une liste si vous avez l'intention d'itérer sur l'IEnumerable plus d'une fois.
Par exemple, LINQ-to-objects est construit sur le principe du "yield return". Si vous avez écrit une requête LINQ lente (par exemple, qui filtre une grande liste en une petite liste, ou qui effectue un tri et un regroupement), il peut être judicieux d'appeler ToList()
sur le résultat de la requête afin d'éviter une énumération multiple (qui exécute en fait la requête plusieurs fois).
Si vous devez choisir entre le "rendement" et le "retour sur investissement", vous devez choisir entre les deux. List<T>
Lorsque vous écrivez une méthode, posez-vous la question suivante : le calcul de chaque élément est-il coûteux et l'appelant aura-t-il besoin d'énumérer les résultats plus d'une fois ? Si vous savez que les réponses sont oui et oui, vous ne devriez pas utiliser la méthode yield return
(sauf si, par exemple, la liste produite est très importante et que vous ne pouvez pas vous permettre la mémoire qu'elle utiliserait. N'oubliez pas qu'un autre avantage de yield
est que la liste des résultats ne doit pas être entièrement en mémoire en même temps).
Une autre raison de ne pas utiliser "yield return" est que l'entrelacement des opérations est dangereux. Par exemple, si votre méthode ressemble à quelque chose comme ceci,
IEnumerable<T> GetMyStuff() {
foreach (var x in MyCollection)
if (...)
yield return (...);
}
Ceci est dangereux s'il y a une chance que MyCollection change à cause d'une action de l'appelant :
foreach(T x in GetMyStuff()) {
if (...)
MyCollection.Add(...);
// Oops, now GetMyStuff() will throw an exception
// because MyCollection was modified.
}
yield return
peut causer des problèmes chaque fois que l'appelant change quelque chose que la fonction cédante suppose ne pas changer.