2012-02-17 24 views
96

A menudo veo a personas que usan Where.FirstOrDefault() hacer una búsqueda y tomar el primer elemento. ¿Por qué no usar Find()? ¿Hay alguna ventaja para el otro? No podría notar la diferencia.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 ");' es más conciso que utilizar tanto '.Where' como' .FirstOrDefault'. –

+0

@Kirk, supongo que mi siguiente pregunta sería por qué agregaron el hallazgo. Ese es un buen consejo. Lo único que se me ocurre es que FirstOrDefault podría devolver un valor por defecto distinto de null. De lo contrario, parece una adición sin sentido. – KingOfHypocrites

+6

'Encontrar' es anterior a LINQ. (estaba disponible en .NET 2.0 y no se podía usar lambdas. Se le forzó a usar métodos normales o métodos anónimos) –

Respuesta

138

¿Dónde está el método Find en IEnumerable<T>? (Pregunta retórica.)

Los métodos Where y FirstOrDefault son aplicables contra múltiples tipos de secuencias, incluyendo List<T>, T[], Collection<T>, etc. Cualquier secuencia que implementa IEnumerable<T> puede utilizar estos métodos. Find está disponible solo para List<T>. Los métodos que generalmente son más aplicables, son más reutilizables y tienen un mayor impacto.

Supongo que mi siguiente pregunta sería por qué agregaron el hallazgo. Ese es un buen consejo. Lo único que se me ocurre es que FirstOrDefault podría devolver un valor por defecto distinto de null. De lo contrario, apenas se parece como una adición inútil

Find en List<T> es anterior a la de otros métodos. List<T> se agregó con genéricos en .NET 2.0 y Find fue parte de la API para esa clase. Where y FirstOrDefault se agregaron como métodos de extensión para IEnumerable<T> con Linq, que es una versión posterior de .NET. No puedo decir con certeza que si Linq existía con la versión 2.0 que Find nunca se habría agregado, pero podría decirse que es el caso para muchas otras características que vinieron en versiones anteriores de .NET que se volvieron obsoletas o redundantes en versiones posteriores.

+0

Excelente respuesta. Gracias. – KingOfHypocrites

+50

Solo para complementar: no es necesario llamar a Where y First or FirstOrDefault: First or FirstOrDefault le permite especificar un predicado de búsqueda, haciendo que Where call innecesaria –

22

Find sólo es implemented en List<T>, mientras Where().FirstOrDefault() funciona con todos los IEnumerable<T>.

34

Acabo de enterarme hoy, haciendo algunas pruebas en una lista de objetos 80K y descubrí que Find() puede ser hasta 1000% más rápido que usando Where con FirstOrDefault(). No lo sabía hasta probar un cronómetro antes y después de cada uno. A veces era el mismo tiempo, de lo contrario, era más rápido.

+5

¿Lo intentó con Where AND FirstOrDefault? Si lo hizo, quizás lo intente solo con FirstOrDefault y vea si Find() es aún mejor. – MVCKarl

+1

@MVCKarl pls ver [aquí] (http://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault). Encontrar es realmente más rápido casi dos veces.Pero no puedo entender si esto se debe solo a la sobrecarga del Enumerador. –

+3

Parece que no se materializó el resultado con '.ToList()' o '.ToArray()' para realizar realmente la consulta. –

12

Existe una diferencia muy importante si el origen de los datos es Entity Framework: Find encontrará entidades en el estado "agregado" que aún no se han conservado, pero Where no lo hará. Esto es por diseño.

Cuestiones relacionadas