2012-02-17 6 views
96

Spesso vedo persone che utilizzano Where.FirstOrDefault() effettuare una ricerca e afferrare il primo elemento. Perché non usare solo Find()? C'è un vantaggio per l'altro? Non potrei dire una differenza.Find() vs. Where(). FirstOrDefault()

namespace LinqFindVsWhere 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> list = new List<string>(); 
      list.AddRange(new string[] 
      { 
       "item1", 
       "item2", 
       "item3", 
       "item4" 
      }); 

      string item2 = list.Find(x => x == "item2"); 
      Console.WriteLine(item2 == null ? "not found" : "found"); 
      string item3 = list.Where(x => x == "item3").FirstOrDefault(); 
      Console.WriteLine(item3 == null ? "not found" : "found"); 
      Console.ReadKey(); 
     } 
    } 
} 
+33

FWIW, 'list.FirstOrDefault (x => x ==" item3 ");' è più conciso rispetto all'utilizzo di '.Where' e' .FirstOrDefault'. –

+0

@Kirk, immagino che la mia prossima domanda sia perché hanno aggiunto il risultato. Questo è un buon consiglio. L'unica cosa che posso pensare è che il FirstOrDefault potrebbe restituire un valore predefinito diverso diverso da null. Altrimenti sembra un'aggiunta inutile. – KingOfHypocrites

+6

'Trova' precedente a LINQ. (era disponibile in .NET 2.0 e non si poteva usare lambdas. Si è costretti a usare metodi normali o metodi anonimi) –

risposta

138

Dove è il metodo Find su IEnumerable<T>? (Domanda retorica.)

I Where e FirstOrDefault metodi sono applicabili contro molteplici tipi di sequenze, tra List<T>, T[], Collection<T>, ecc Qualsiasi sequenza che implementa IEnumerable<T> possono utilizzare questi metodi. Find è disponibile solo per List<T>. I metodi generalmente più applicabili sono quindi più riutilizzabili e hanno un impatto maggiore.

Immagino che la mia prossima domanda sia perché hanno aggiunto il risultato. Questo è un buon consiglio. L'unica cosa che posso pensare è che il FirstOrDefault potrebbe restituire un valore predefinito diverso diverso da null. Altrimenti sembra un'aggiunta inutile

Find su List<T> precedente agli altri metodi. List<T> è stato aggiunto con generici in .NET 2.0 e Find faceva parte dell'API per quella classe. Where e FirstOrDefault sono stati aggiunti come metodi di estensione per IEnumerable<T> con Linq, che è una versione .NET successiva. Non posso dire con certezza che se Linq esistesse con la versione 2.0, Find non sarebbe mai stato aggiunto, ma questo è probabilmente il caso di molte altre funzionalità che sono venute in versioni precedenti di .NET rese obsolete o ridondanti dalle versioni successive.

+0

Ottima risposta. Grazie. – KingOfHypocrites

+50

Solo per completare: non è necessario chiamare Where and First o FirstOrDefault: First or FirstOrDefault consente di specificare un predicato di ricerca, rendendo la chiamata Where non necessaria –

22

Find è solo implemented in List<T>, mentre Where().FirstOrDefault() funziona con tutti i IEnumerable<T>.

34

Ho appena scoperto oggi, eseguendo alcuni test su un elenco di oggetti 80K e ho rilevato che Find() può essere fino al 1000% più veloce rispetto all'utilizzo di Where con FirstOrDefault(). Non lo sapevo fino a quando non testavo un timer prima e dopo tutti. A volte era la stessa ora, altrimenti era più veloce.

+5

Hai provato con Where AND FirstOrDefault? Se lo hai fatto, provalo solo con FirstOrDefault e vedi se Find() è ancora migliore. – MVCKarl

+1

@MVCKarl pls vedere [qui] (http://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault). Trova è davvero più veloce quasi due volte.Ma non riesco a capire questo a causa di nessun overhead Enumerator solo? –

+3

Sembra che tu non abbia materializzato il risultato con un '.ToList()' o '.ToArray()' per eseguire effettivamente la query. –

12

C'è una differenza molto importante se la fonte dei dati è Entity Framework: Find troverà le entità nello stato "aggiunto" che non sono ancora persistenti, ma non lo sarà Where. Questo è di design.