Ответ
Сигнатура метода расширения Where для IQueryable<T> отличается от такового для IEnumerable<T> типом параметра predicate.
// Сигнатура для IQueryable<T>
public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
System.Linq.Expressions.Expression<Func<TSource, bool>> predicate // Ключевое отличие!
)
Ключевое отличие: Второй параметр — это дерево выражений (Expression), а не просто делегат (Func<TSource, bool>). Это позволяет провайдерам LINQ (как EF Core) анализировать логику предиката и транслировать ее в целевой язык запросов (например, SQL).
Пример использования с Entity Framework Core:
using (var context = new AppDbContext())
{
// Запрос строится как Expression и преобразуется в SQL
IQueryable<User> adultUsersQuery = context.Users
.Where(u => u.Age >= 18 && u.IsActive); // u => ... компилируется в Expression<Func<User, bool>>
// SQL не выполняется до материализации (ToList, FirstOrDefault и т.д.)
List<User> adultUsers = adultUsersQuery.ToList();
}
Сравнение с IEnumerable.Where:
// Для IEnumerable<T> - предикат как делегат, фильтрация происходит в памяти
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate // Простой делегат
);
List<User> usersList = GetUsersFromMemory();
// Фильтрация происходит в памяти .NET после загрузки всех данных
var filteredUsers = usersList.Where(u => u.Age >= 18).ToList();
Практический вывод: Использование IQueryable<T>.Where с Expression позволяет выполнять фильтрацию на стороне базы данных, что критически важно для производительности при работе с большими объемами данных.