Linq, где ключевое слово, по сравнению с Где дополнительные и Параметры выражения

Передача в Выражении к запросу Linq ведет себя по-другому в зависимости от синтаксиса, используемого, и интересно почему дело обстоит так.

Скажем, у меня есть эта очень родовая функция

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause)

Следующая реализация работает как ожидалось

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause)
{
    return (from c in _ctx.Companies.Where(whereClause) select c);
}

Но эта следующая реализация не компилирует (Делегат 'Система. Func' не берет 1 аргумент),

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause)
{
    return (from c in _ctx.Companies where whereClause select c);
}

Очевидно, я могу просто использовать первый синтаксис, но я просто задавался вопросом, почему компилятор не рассматривает где ключевое слово то же как Где расширение?

Спасибо, Thomas

6
задан 5 March 2010 в 11:23
поделиться

3 ответа

Синтаксис для выражения запроса, содержащего предложение , где есть (упрощение полной грамматики)

from identifier in expression where boolean-expression select expression

, где предложение не логическое выражение. Чтобы процитировать это, вы должны сказать

from c in _ctx.Companies where whereClause.Compile()(c) select c;

Обратите внимание, что если whereClause было Func , вы могли бы уйти с

from c in _ctx.Companies where whereClause(c) select c;

Обратите внимание, что

from x in e where f

переведено «механически» компилятором в

(from x in e).Where(x => f)

я говорю «механически», потому что он выполняет это преобразование без какого-либо семантического анализа для проверки правильности вызовов методов и т. д. Этот этап наступает позже, после того как все выражения запроса переведены в выражения вызова метода LINQ.

В частности,

from c in _ctx.Companies where whereClause select c

переведено на

_ctx.Companies.Where(c => whereClause).Select(c)

, что явно бессмысленно.

Причина, по которой

from c in _ctx.Companies.Where(whereClause) select c

является допустимым, заключается в том, что IEnumerable . Где имеет перегрузку, принимающую Func , и существует неявное преобразование из Выражение > в Func .

3
ответ дан 17 December 2019 в 04:45
поделиться

Фактически вы можете сократить все это до:

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause)
{
    return _ctx.Companies.Where(whereClause);
}

При использовании синтаксиса LINQ код в предложении , где переведено в Выражение <> , которое представляет собой кодовое дерево. Когда вы принимаете Expression > , вы говорите, что ваш метод принимает кодовое дерево, которое компилятор преобразует из кода C #.

Поскольку у вас уже есть кодовое дерево, вы должны передать его напрямую методу Where () , а не использовать синтаксис LINQ.

2
ответ дан 17 December 2019 в 04:45
поделиться

Разница в том, что в sql-методе where ожидается выражение, которое оценивается в bool. Но в методе Where тип выражения может быть делегатом.

чтобы заставить второй работать, можно изменить на whereClause.Compile()(c) или изменить параметр на Func whereClause и whereClause(c)

0
ответ дан 17 December 2019 в 04:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: