2008-08-23 4 views
8

Quelle est la meilleure façon de trouver quelque chose dans une liste? Je sais que LINQ a quelques bonnes astuces, mais aussi des suggestions pour C# 2.0. Permet d'obtenir les meilleurs refactorings pour ce modèle de code commun.Le moyen le plus propre de trouver une correspondance dans une liste

Actuellement, j'utiliser le code comme ceci:

// mObjList is a List<MyObject> 
MyObject match = null; 
foreach (MyObject mo in mObjList) 
{ 
    if (Criteria(mo)) 
    { 
     match = mo; 
     break; 
    } 
} 

ou

// mObjList is a List<MyObject> 
bool foundIt = false; 
foreach (MyObject mo in mObjList) 
{ 
    if (Criteria(mo)) 
    { 
     foundIt = true; 
     break; 
    } 
} 

Répondre

14

@ Konrad: Alors, comment l'utilisez-vous? Disons que je veux faire correspondre mo.ID à magicNumber.

En C# 2.0 vous écririez:

result = mObjList.Find(delegate(int x) { return x.ID == magicNumber; }); 

3,0 sait lambdas:

result = mObjList.Find(x => x.ID == magicNumber); 
1

Insérez le code dans une méthode et vous enregistrez un temporaire et un break (et vous recycler code, en prime) :

T Find<T>(IEnumerable<T> items, Predicate<T> p) { 
    foreach (T item in items) 
     if (p(item)) 
      return item; 

    return null; 
} 

... mais bien sûr, cette méthode existe déjà de toute façon pour les listes, même dans .NET 2.0.

4

utilisant une expression lambda:

List<MyObject> list = new List<MyObject>(); 

// populate the list with objects.. 

return list.Find(o => o.Id == myCriteria); 
1

De toute évidence le succès de la performance de l'anonymat Les délégués sont assez importants.

Code d'essai:

static void Main(string[] args) 
    { 
     for (int kk = 0; kk < 10; kk++) 
     { 
      List<int> tmp = new List<int>(); 
      for (int i = 0; i < 100; i++) 
       tmp.Add(i); 
      int sum = 0; 
      long start = DateTime.Now.Ticks; 
      for (int i = 0; i < 1000000; i++) 
       sum += tmp.Find(delegate(int x) { return x == 3; }); 
      Console.WriteLine("Anonymous delegates: " + (DateTime.Now.Ticks - start)); 


      start = DateTime.Now.Ticks; 
      sum = 0; 
      for (int i = 0; i < 1000000; i++) 
      { 
       int match = 0; 
       for (int j = 0; j < tmp.Count; j++) 
       { 
        if (tmp[j] == 3) 
        { 
         match = tmp[j]; 
         break; 
        } 
       } 
       sum += match; 
      } 
      Console.WriteLine("Classic C++ Style: " + (DateTime.Now.Ticks - start)); 
      Console.WriteLine(); 
     } 
    } 

Résultats:

Anonymous delegates: 710000 
Classic C++ Style: 340000 

Anonymous delegates: 630000 
Classic C++ Style: 320000 

Anonymous delegates: 630000 
Classic C++ Style: 330000 

Anonymous delegates: 630000 
Classic C++ Style: 320000 

Anonymous delegates: 610000 
Classic C++ Style: 340000 

Anonymous delegates: 630000 
Classic C++ Style: 330000 

Anonymous delegates: 650000 
Classic C++ Style: 330000 

Anonymous delegates: 620000 
Classic C++ Style: 330000 

Anonymous delegates: 620000 
Classic C++ Style: 340000 

Anonymous delegates: 620000 
Classic C++ Style: 400000 

Dans tous les cas, en utilisant les délégués anonymes est environ 100% plus lent que l'inverse.

+1

Non, la performance atteinte ici n'utilise pas le délégué. Vos algorithmes fonctionnent fondamentalement différemment, la première méthode a un temps d'exécution asymptotique O (n^2) tandis que la seconde a un temps d'exécution O (n). Cela n'a rien à voir avec les délégués mais plutôt avec l'utilisation de la fonction 'Find' dans ce contexte. –

Questions connexes