LINQ, Where () vs FindAll ()

Odpowiedzi:

203

FindAll()jest funkcją List<T>typu, nie jest to metoda rozszerzenia LINQ, taka jak Where. Metody rozszerzenia LINQ działają na każdym typie, który implementuje IEnumerable, natomiast FindAllmogą być używane tylko w List<T>wystąpieniach (lub oczywiście w wystąpieniach klas, które dziedziczą po nim).

Dodatkowo różnią się faktycznym przeznaczeniem. Wherezwraca instancję, IEnumerablektóra jest wykonywana na żądanie, gdy obiekt jest wyliczany. FindAllzwraca nowy, List<T>który zawiera żądane elementy. FindAlljest bardziej jak wywołanie Where(...).ToList()wystąpienia IEnumerable.

Adam Robinson
źródło
20
Tak, gdzie jest leniwa wersja findall
Pierreten,
2
code.msdn.microsoft.com/LINQ-Query-Execution-ce0d3b95 wyjaśnia różnice między opóźnionym (odroczonym) a natychmiastowym wykonaniem. Zasadniczo w niektórych przypadkach nie potrzebujesz całej listy, możesz chcieć przejrzeć elementy, aż coś się stanie, a następnie zatrzymać. Tutaj przydaje się lenistwo, ale w zależności od implementacji może prowadzić do nieprzewidywalnych rezultatów (wszystko wyjaśniono w linku). Mam nadzieję że to pomoże.
nurchi
10

Największą różnicą dla mnie jest to, że .FindAll jest również dostępny w .Net 2.0. Nie zawsze mam luksus programowania w .Net 3.5, więc staram się zapamiętać „natywne” metody ogólnych kolekcji .Net.

Kilka razy zdarzyło się, że sam zaimplementowałem już dostępną metodę List, ponieważ nie mogłem jej LINQ.

Co mogę znaleźć przydatne w tym przypadku jest to, że przy użyciu VS2008, I można użyć typu wnioskowania i składni lambda. Są to funkcje kompilatora, a nie funkcje platformy. Oznacza to, że mogę to napisać i nadal pozostać w .Net 2.0:

var myOddNums = myNums.FindAll(n => n%2==1);

Ale jeśli masz dostępne LINQ, ważne jest zachowanie różnicy między odroczonym wykonaniem a natychmiastowym wykonaniem.

cfern
źródło
6

Jeśli dobrze pamiętam, główna różnica (poza tym, co są zaimplementowane w: IEnumerable<T>vs. List<T>) polega na tym, że Whereimplementuje odroczone wykonanie, w którym faktycznie nie wykonuje wyszukiwania, dopóki go nie potrzebujesz - na przykład używając go w pętli foreach. FindAlljest metodą natychmiastowego wykonania.

WayneC
źródło
3

Wykonałem kilka testów na liście obiektów 80 tys. I stwierdziłem, że Find()może to być nawet o 1000% szybsze niż użycie Wherez FirstOrDefault(). Nie wiedziałem o tym, dopóki nie przetestowałem timera przed i po każdym połączeniu. Czasami był to ten sam czas, innym razem szybciej.

digiben
źródło
5
Czy też próbowałeś uzyskać dostęp do kolekcji? Enumerable.Where () używa odroczonego wykonania i nie jest oceniane przed uzyskaniem dostępu do kolekcji, co może prowadzić do fałszywych koncepcji dotyczących tego, czy faktycznie jest ona szybsza, czy nie. Mimo to w przeważającej części zwykle szybciej używa się wyliczalnych niż statycznych kolekcji (takich jak Type <T> i Array <T>).
Sebastian Job Bjørnager Jensen
Pytanie dotyczy FindAll. Jest oczywiste, że Find będzie szybszy niż Where (biorąc wszystkie wartości) i otrzymanie FirstOrDefault
Vivek MVK