web-dev-qa-db-fra.com

Liste générique FindAll () vs. foreach

Je regarde une liste générique pour trouver des articles basés sur un certain paramètre.

En général, quelle serait la mise en œuvre la meilleure et la plus rapide?
1. Parcourez chaque élément de la liste, enregistrez chaque match dans une nouvelle liste et renvoyez-le.

foreach(string s in list)
{ 
    if(s == "match")
    {
       newList.Add(s);
    }
} 

return newList;

Ou
2. Utilisation de la méthode FindAll et transmission d'un délégué.

newList = list.FindAll(delegate(string s){return s == "match";});

Est-ce qu'ils ne courent pas tous les deux en ~ O (N)? Quelle serait la meilleure pratique ici?

Cordialement, Jonathan

29
jon37

Vous devez absolument utiliser la méthode FindAll ou la méthode LINQ équivalente. Pensez également à utiliser le lambda plus concis à la place de votre délégué si vous le pouvez (nécessite C # 3.0):

var list = new List<string>();
var newList = list.FindAll(s => s.Equals("match"));
45
Egil Hansen

Jonathan,

Vous trouverez une bonne réponse à cette question au chapitre 5 (Considérations sur les performances) de Linq To Action

Ils mesurent a pour chaque recherche qui s’exécute environ 50 fois et qui aboutit avec foreach = 68ms par cycle/List.FindAll = 62ms par cycle En réalité, il serait probablement dans votre intérêt de simplement créer un test et de constater par vous-même.

5
matt_dev

List.FindAll est O(n) et va parcourir toute la liste.

Si vous souhaitez exécuter votre propre itérateur avec foreach, je vous recommande d'utiliser l'instruction de rendement et de renvoyer un IEnumerable si possible. De cette façon, si vous n'avez plus besoin que d'un élément de votre collection, ce sera plus rapide (vous pouvez arrêter votre appelant sans épuiser toute la collection).

Sinon, restez sur l'interface BCL.

4
Reed Copsey

Toute différence de performance va être extrêmement mineure. Je suggérerais FindAll pour la clarté, ou, si possible, Enumerable.Where. Je préfère utiliser les méthodes Enumerable car elles permettent une plus grande flexibilité dans la refactorisation du code (vous ne prenez pas de dépendance sur List<T>).

3
Daniel Pratt

Oui, les deux implémentations sont O (n). Ils doivent examiner chaque élément de la liste pour trouver toutes les correspondances. En termes de lisibilité, je préférerais aussi FindAll. Pour des considérations sur les performances, consultez LINQ en action (Chapitre 5.3). Si vous utilisez C # 3.0, vous pouvez également appliquer une expression lambda. Mais ce n'est que la cerise sur le gâteau:

var newList = aList.FindAll(s => s == "match");
2
olli-MSFT

Je suis avec les Lambdas

List<String> newList = list.FindAll(s => s.Equals("match"));
1
MRFerocius

À moins que l'équipe C # n'ait amélioré les performances de LINQ et FindAll, l'article suivant semble suggérer que for et foreach surpasseraient LINQ et FindAll lors de l'énumération d'objets: LINQ on Object Performance

Cet article a été publié en mars 2009, juste avant que ce poste ne soit initialement demandé.

0
William Niu