Методы расширения LINQ - Any() vs. Where() vs. Exists()
К сожалению, имена этих методов делают ужасные условия поиска, и я не смог найти хороший ресурс, который объясняет разницу между этими методами - как в том, когда использовать каждый.
Спасибо.
Edit:
Тип запроса, который я пытаюсь полностью понять, выглядит примерно так:
context.Authors.Where(a => a.Books.Any(b => b.BookID == bookID)).ToList();
И спасибо всем, кто ответил.
Ответы
Ответ 1
Where
возвращает новую последовательность элементов, соответствующих предикату.
Any
возвращает логическое значение; там версия с предикатом (в этом случае она возвращает, соответствуют ли какие-либо элементы) и версия без (в этом случае она возвращает, содержит ли запрос до сих пор какие-либо элементы).
Я не уверен в Exists
- это не стандартный оператор запроса LINQ. Если есть версия для Entity Framework, возможно, она проверяет существование на основе ключа - своего рода специализированную форму Any
? (Там Exists
метод в List<T>
, который похож на Any(predicate)
, но предшествует LINQ.)
Ответ 2
context.Authors.Where(a = > a.Books.Any(b = > b.BookID == bookID)). ToList();
a.Books
- список книг этого автора. Свойство автоматически создается Linq-to-Sql, если у вас установлено отношение внешних ключей.
Итак, a.Books.Any(b => b.BookID == bookID)
переводится как "У любой из книг этого автора есть идентификатор bookID", что делает полное выражение "Кто является авторами книги с id bookID?"
Это также может быть написано как
from a in context.Authors
join b in context.Books on a.AuthorId equal b.AuthorID
where b.BookID == bookID
select a;
UPDATE: Any()
насколько мне известно, возвращает bool
. Его эффективная реализация:
public Any(this IEnumerable<T> coll, Func<T, bool> predicate)
{
foreach(T t in coll)
{
if (predicte(t))
return true;
}
return false;
}
Ответ 3
Просто чтобы найти его в следующий раз, вот как вы ищите перечислимые расширения Linq. Методами являются статические методы Enumerable, поэтому Enumerable.Any, Enumerable.Where и Enumerable.Exists.
Поскольку третий не возвращает никакого полезного результата, я обнаружил, что вы имели в виду List.Exists, таким образом:
Я также рекомендую hookedonlinq.com, поскольку у этого есть очень подробные и понятные руководства, а также четкие объяснения поведения методов Linq в отношение к отсрочке и ленивости.
Ответ 4
Любая логическая функция, возвращающая значение true, если любой из объектов в списке удовлетворяет условию, заданному в параметрах функции. Например:
List<string> strings = LoadList();
boolean hasNonEmptyObject = strings.Any(s=>string.IsNullOrEmpty(s));
Где - функция, которая возвращает список со всеми объектами в списке, которые удовлетворяют условию, заданному в параметрах функции. Например:
IEnumerable<string> nonEmptyStrings = strings.Where(s=> !string.IsNullOrEmpty(s));
Существует - в основном то же самое, что и любое, но не общее - оно определено в классе List, а Any определено в интерфейсе IEnumerable.
Ответ 5
IEnumerable вводит довольно много расширений, которые помогают вам передать свой собственный делегат и вызвать результирующий результат из IEnumerable. Большинство из них по характеру типа Func
Func принимает аргумент T и возвращает TResult.
В случае
Где - Func: так требуется IEnumerable из T и возвращает bool. То, где в конечном итоге вернет IEnumerable из T, для которого Func возвращает true.
Итак, если у вас есть 1,5,3,6,7 как IEnumerable, и вы пишете .where(r = > r < 5), он вернет новый IEnumerable из 1,3.
Any - Func в основном похож на подпись, но возвращает true только тогда, когда любой из критериев возвращает true для IEnumerable. В нашем случае он будет возвращать true, поскольку имеется несколько элементов с r < 5.
Exists - Предикат, с другой стороны, вернет true только тогда, когда любой из предикатов возвращает true.
Поэтому в нашем случае, если вы пройдете .Exists(r = > 5) вернет true, поскольку 5 - это элемент, присутствующий в IEnumerable.
Ответ 6
Any() возвращает true, если какой-либо из элементов в коллекции соответствует вашим критериям предиката.
Где() возвращает перечислимый из всех элементов в коллекции, которые соответствуют вашим критериям предиката.
Exists() делает то же самое, что и все, кроме как только более старая реализация, которая была там на IList еще до Linq.