Używając LINQ w kolekcjach, jaka jest różnica między następującymi wierszami kodu?
if(!coll.Any(i => i.Value))
i
if(!coll.Exists(i => i.Value))
Aktualizacja 1
Po rozłożeniu .Exists
wygląda na to, że nie ma kodu.
Aktualizacja 2
Czy ktoś wie, dlaczego nie ma tam kodu?
c#
linq
collections
Anthony D.
źródło
źródło
Odpowiedzi:
Zobacz dokumentację
List.Exists (Metoda obiektowa - MSDN)
Istnieje od wersji .NET 2.0, a więc przed LINQ. Przeznaczony do użytku z delegatem Predicate , ale wyrażenia lambda są kompatybilne wstecz. Ponadto, tylko Lista ma to (nawet IList)
IEnumerable.Any (Metoda rozszerzenia - MSDN)
Jest to nowość w .NET 3.5 i używa jako argumentu Func (TSource, bool), więc było to przeznaczone do użycia z wyrażeniami lambda i LINQ.
W zachowaniu są identyczne.
źródło
List<>
metod instancji .NET 2 .Różnica polega na tym, że Any jest metodą rozszerzenia dowolnej
IEnumerable<T>
zdefiniowanej w System.Linq.Enumerable. Można go użyć w dowolnejIEnumerable<T>
instancji.Istnienie nie wydaje się być metodą rozszerzenia. Domyślam się, że coll jest typu
List<T>
. Jeśli tak, istnieje jest instancją, która działa bardzo podobnie do Any.Krótko mówiąc , metody są zasadniczo takie same. Jedno jest bardziej ogólne niż drugie.
źródło
TLDR; Wydajność
Any
wydaje się być wolniejsza (jeśli odpowiednio to skonfigurowałem, aby oszacować obie wartości w tym samym czasie)generator listy testów:
Z 10 milionami rekordów
Z rekordami 5 mln
Z rekordami 1 mln
Z 500k (zmieniłem też kolejność, w jakiej są oceniane, aby sprawdzić, czy nie ma żadnej dodatkowej operacji związanej z tym, który biegnie pierwszy).
Ze 100 000 rekordów
Wydaje
Any
się być wolniejszy o 2 wielkości.Edycja: W przypadku rekordów 5 i 10M zmieniłem sposób, w jaki generuje listę i
Exists
nagle zwolniłem,Any
co sugeruje, że coś jest nie tak w trakcie testowania.Nowy mechanizm testowania:
Edit2: Ok, więc aby wyeliminować wpływ generowania danych testowych, zapisałem wszystko do pliku, a teraz go czytam.
10 mln
5 mln
1 mln
500 tys
źródło
Jako kontynuacja odpowiedzi Matasa na temat testów porównawczych.
TL / DR : Exists () i Any () są równie szybkie.
Po pierwsze: Benchmarking przy użyciu stopera nie jest precyzyjny ( patrz odpowiedź series0ne na inny, ale podobny temat ), ale jest znacznie bardziej precyzyjny niż DateTime.
Sposobem na uzyskanie bardzo precyzyjnych odczytów jest profilowanie wydajności. Ale jednym ze sposobów, aby dowiedzieć się, w jaki sposób wydajność obu metod mierzy się względem siebie, jest wykonanie obu metod mnóstwo razy, a następnie porównanie najszybszego czasu wykonania każdej z nich. W ten sposób naprawdę nie ma znaczenia, że JITing i inne szumy dają nam złe odczyty (i tak się dzieje ), ponieważ obie egzekucje są w pewnym sensie „ równie mylące ”.
Po wykonaniu powyższego kodu 4 razy (co z kolei daje 1 000
Exists()
iAny()
na liście zawierającej 1 000 000 elementów), nietrudno zauważyć, że metody są prawie równie szybkie.Jest to niewielka różnica, ale jest zbyt mała różnica, aby nie być wyjaśnione przez szum tła. Domyślam się, że gdyby zrobić 10 000 lub 100 000,
Exists()
aAny()
zamiast tego ta niewielka różnica zniknąłaby mniej więcej.źródło
Dodatkowo zadziała to tylko wtedy, gdy wartość jest typu bool. Zwykle stosuje się to w predykatach. Jakikolwiek predykat byłby ogólnie używany do stwierdzenia, czy jest jakiś element spełniający dany warunek. Tutaj właśnie tworzysz mapę ze swojego elementu i na właściwość bool. Wyszukuje „i”, którego właściwość Value ma wartość true. Po zakończeniu metoda zwróci wartość true.
źródło
Kiedy poprawisz pomiary - jak wspomniano powyżej: Any i Exists, i dodając średnią - otrzymamy następujące dane wyjściowe:
źródło