w System.Linq
przestrzeni nazw, możemy rozszerzyć nasze IEnumerable jest mieć Obojętnie () i count () metody rozszerzenie .
Ostatnio powiedziano mi, że jeśli chcę sprawdzić, czy kolekcja zawiera 1 lub więcej elementów, powinienem użyć .Any()
metody rozszerzenia zamiast .Count() > 0
metody rozszerzenia, ponieważ .Count()
metoda rozszerzenia musi iterować wszystkie elementy.
Po drugie, niektóre kolekcje mają właściwość (nie metodę rozszerzenia), którą jest Count
lub Length
. Czy lepiej byłoby użyć ich zamiast .Any()
lub .Count()
?
tak / nie?
.net
linq
performance
.net-3.5
extension-methods
Pure.Krome
źródło
źródło
Odpowiedzi:
Jeśli zaczynasz z czymś, co ma
.Length
lub.Count
(takich jakICollection<T>
,IList<T>
,List<T>
itp) - wtedy będzie to najszybsza opcja, ponieważ nie muszą przejść przezGetEnumerator()
/MoveNext()
/Dispose()
sekwencji wymaganychAny()
do sprawdzenia niepustyIEnumerable<T>
sekwencji .Za jedyne
IEnumerable<T>
, toAny()
będzie na ogół szybciej, ponieważ ma tylko spojrzeć na jednej iteracji. Należy jednak pamiętać, że implementacja LINQ-ObjectsCount()
sprawdzaICollection<T>
(używa.Count
jako optymalizację) - więc jeśli źródłowym źródłem danych jest bezpośrednio lista / kolekcja, nie będzie dużej różnicy. Nie pytaj mnie, dlaczego nie korzysta z niejakiego rodzajuICollection
...Oczywiście, jeśli użyłeś LINQ do filtrowania itp.
Where
, Będziesz miał sekwencję opartą na bloku iteratora, więc taICollection<T>
optymalizacja jest bezużyteczna.Ogólnie z
IEnumerable<T>
: trzymaj sięAny()
;-pźródło
(somecollection.Count > 0)
? Czy cały nasz kod przed wprowadzeniem metody LINQ .Any () był trudny do zrozumienia?someCollection.Count > 0
jest to tak samo jasne, jaksomeCollection.Any()
i ma dodatkową zaletę polegającą na większej wydajności i niewymaganiu LINQ. To prawda, że jest to bardzo prosty przypadek, a inne konstrukcje korzystające z operatorów LINQ przekazują intencje programistów znacznie jaśniej niż równoważna opcja inna niż LINQ.Uwaga: napisałem tę odpowiedź, gdy Entity Framework 4 był aktualny. Celem tej odpowiedzi nie było przejście do testów trywialnych
.Any()
vs.Count()
wydajnościowych. Chodziło o to, aby zasygnalizować, że EF jest daleki od ideału. Nowsze wersje są lepsze ... ale jeśli masz część kodu, który jest wolny i używa EF, przetestuj z bezpośrednim TSQL i porównaj wydajność zamiast polegać na założeniach (.Any()
to ZAWSZE jest szybsze niż.Count() > 0
).Chociaż zgadzam się z większością głosowanych odpowiedzi i komentarzy - szczególnie w kwestii
Any
, w której deweloper sygnalizuje zamiary lepsze niżCount() > 0
- miałem sytuację, w której Count jest szybszy o rząd wielkości na SQL Server (EntityFramework 4).Oto zapytanie z
Any
tym wyjątkiem limitu czasu (w ~ 200 000 rekordów):Count
wersja wykonywana w ciągu milisekund:Muszę znaleźć sposób, aby zobaczyć, jaki dokładnie SQL produkują oba LINQ - ale jest oczywiste, że istnieje ogromna różnica w wydajności między,
Count
aAny
w niektórych przypadkach, i niestety wydaje się, że nie możesz po prostu trzymać sięAny
we wszystkich przypadkach.EDYCJA: Tutaj są generowane zapytania SQL. Piękności jak widać;)
ANY
:COUNT
:Wydaje się, że czysty Where with EXISTS działa znacznie gorzej niż obliczanie Count, a następnie wykonywanie Where with Count == 0.
Daj mi znać, jeśli zauważysz jakiś błąd w moich ustaleniach. Bez względu na dyskusję Any vs. Count można wyciągnąć z tego wszystko, że bardziej skomplikowane LINQ jest o wiele lepiej, gdy zostanie przepisane jako procedura przechowywana;).
źródło
Ponieważ jest to dość popularny temat i odpowiedzi różnią się, musiałem przyjrzeć się temu problemowi od nowa.
Testowanie środowiska: EF 6.1.3, SQL Server, 300 000 rekordów
Model stołu :
Kod testowy:
Wyniki:
Any () ~ 3ms
Count () ~ 230ms dla pierwszego zapytania, ~ 400ms dla drugiego
Uwagi:
W moim przypadku EF nie generował kodu SQL takiego jak @Ben wspomnianego w jego poście.
źródło
Count() > 0
. : DEDYCJA: zostało to naprawione w wersji EF 6.1.1. i ta odpowiedź nie jest już aktualna
W przypadku SQL Server i EF4-6 funkcja Count () działa około dwa razy szybciej niż Any ().
Po uruchomieniu Table.Any () wygeneruje coś w rodzaju ( alert: nie rań mózgu próbując to zrozumieć )
który wymaga 2 skanów wierszy z twoim stanem.
Nie lubię pisać,
Count() > 0
bo ukrywa moją intencję. Wolę użyć do tego niestandardowego predykatu:źródło
To zależy, jak duży jest zestaw danych i jakie są wymagania dotyczące wydajności?
Jeśli to nic gigantycznego, użyj najbardziej czytelnej formy, która dla mnie jest dowolna, ponieważ jest krótsza i czytelniejsza niż równanie.
źródło
O Count () metody, jeśli IEnumarable jest ICollection , wtedy nie możemy iterate wszystkich elementów, ponieważ możemy odzyskać hrabiego pole kolekcji ICollection , jeśli IEnumerable nie jest ICollection musimy iterate wszystkich elementów przy użyciu jednocześnie z MoveNext , spójrz .NET Framework Code:
Referencje: Źródło referencyjne Wyliczalne
źródło
Możesz zrobić prosty test, aby to rozgryźć:
Sprawdź wartości testCount i testAny.
źródło
Count
zastąpić metodę Count () vs .Any () nie właściwość. Potrzebujesz czasu na iteracje.Jeśli używasz Entity Framework i masz ogromną tabelę z wieloma rekordami, Any () będzie znacznie szybsze. Pamiętam, jak kiedyś chciałem sprawdzić, czy stół jest pusty i ma miliony wierszy. Zakończenie Count ()> 0 zajęło 20-30 sekund. To było natychmiastowe dzięki Any () .
Any () może zwiększać wydajność, ponieważ może nie być konieczne iterowanie kolekcji w celu uzyskania liczby rzeczy. Musi trafić tylko jeden z nich. Lub, powiedzmy, LINQ-to-Entities, wygenerowany SQL będzie JEŚLI ISTNIEJE (...), a nie WYBIERZ LICZNIK ... lub nawet WYBIERZ * ....
źródło