Często chcę sprawdzić, czy podana wartość pasuje do wartości na liście (np. Podczas sprawdzania poprawności):
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
Ostatnio zauważyłem, że ReSharper prosi mnie o uproszczenie tych zapytań, aby:
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
Oczywiście jest to logicznie identyczne, być może nieco bardziej czytelne (jeśli zrobiłeś dużo matematyki), moje pytanie brzmi: czy to prowadzi do wydajności?
Wydaje się, że powinien (tzn. .Any()
Brzmi jak zwiera, podczas gdy .All()
brzmi tak, jakby nie), ale nie mam na to dowodów. Czy ktoś ma głębszą wiedzę, czy zapytania rozwiążą to samo, czy też ReSharper prowadzi mnie na manowce?
if (!sequence.Any(v => v == true))
. Jeśli chcesz kontynuować, czy wszystko jest zgodny z określoną specyfikacją:if (sequence.All(v => v < 10))
.Odpowiedzi:
Wdrożenie
All
zgodnie z ILSpy (jak w rzeczywistości poszedłem i spojrzałem, zamiast „dobrze, ta metoda działa trochę jak ...” Mogę to zrobić, jeśli omawiamy teorię, a nie wpływ).Implementacja
Any
zgodnie z ILSpy:Oczywiście może występować niewielka różnica w wytwarzanej IL. Ale nie, nie, nie ma. IL jest prawie taka sama, ale dla oczywistej inwersji zwracania wartości true w przypadku dopasowania predykatu w porównaniu do zwracania wartości false w przypadku niedopasowania predykatu.
Oczywiście jest to tylko linq dla obiektów. Możliwe, że jakiś inny dostawca linq traktuje jednego znacznie lepiej od drugiego, ale jeśli tak było, to raczej losowe, który otrzymał bardziej optymalną implementację.
Wydaje się, że reguła sprowadza się wyłącznie do tego, że ktoś czuje, że
if(determineSomethingTrue)
jest prostszy i bardziej czytelny niżif(!determineSomethingFalse)
. I szczerze mówiąc, myślę, że mają one trochę racji w tym, że często mylę sięif(!someTest)
*, gdy istnieje alternatywny test o równej gadatliwości i złożoności, który zwróciłby prawdę w przypadku warunku, na którym chcemy działać. Ale tak naprawdę, osobiście nie znajduję nic, co by sprzyjało jednej z dwóch alternatyw, które dajesz, i być może pochyliłbym się bardzo nieznacznie do pierwszej, gdyby orzeczenie było bardziej skomplikowane.* Nie mylące jak w nie rozumiem, ale mylące jak w martwię się, że istnieje jakiś subtelny powód decyzji, której nie rozumiem, i kilka mentalnych przeskoków zdaje sobie sprawę, że „nie, po prostu postanowili to zrobić w ten sposób, poczekaj, po co znów patrzyłem na ten fragment kodu? ... "
źródło
Any
powróci,false
a zatem!Any
powrócitrue
, więc są identyczne.!test.Any(x => x.Key == 3 && x.Value == 1)
tych zastosowańAll
jesttest.All(x => !(x.Key == 3 && x.Value == 1))
(co w istocie jest równoważnetest.All(x => x.Key != 3 || x.Value != 1)
).Może się okazać, że te metody rozszerzeń czynią kod bardziej czytelnym:
Teraz zamiast twojego oryginału
można powiedzieć
źródło
Oba miałyby identyczną wydajność, ponieważ oba zatrzymują wyliczanie po wyniku -
Any()
na pierwszym elemencie przekazywany predykat oceniatrue
iAll()
na pierwszym elemencie, na którym ocenia predykatfalse
.źródło
All
zwarcia przy pierwszym braku dopasowania, więc nie stanowi to problemu.Jednym z obszarów subtelności jest to
Jest prawdziwy. Wszystkie elementy w sekwencji są parzyste.
Więcej informacji na temat tej metody można znaleźć w dokumentacji Enumerable.All .
źródło
bool allEven = !Enumerable.Empty<int>().Any(i => i % 2 != 0)
to też prawda.All()
określa, czy wszystkie elementy sekwencji spełniają warunek.Any()
określa, czy jakikolwiek element sekwencji spełnia warunek.źródło
Według tego linku
źródło
Jak dobrze ujęto inne odpowiedzi: nie chodzi o wydajność, chodzi o przejrzystość.
Istnieje szeroka obsługa obu opcji:
Myślę jednak, że może to zapewnić szersze wsparcie :
Po prostu obliczenie wartości logicznej (i nadanie jej nazwy) przed negowaniem czegokolwiek bardzo to wyjaśnia.
źródło
Jeśli spojrzysz na źródło Enumerable , zobaczysz, że implementacja
Any
iAll
jest dość blisko:Nie ma możliwości, aby jedna metoda była znacznie szybsza od drugiej, ponieważ jedyna różnica polega na boolowskiej negacji, więc wolę czytelność niż fałszywą wydajność.
źródło