Этот вопрос уже имеет ответ здесь:
Как пример, почему большинство операторов LINQ принимает Expression
и его эквивалент Func
?
Каково преимущество/причина для использования дженерика Expression
класс вместо прямого синтаксис лямбды?
Используя Expression
, вы явно создаете дерево выражений - это означает, что вы можете работать с кодом, составляющим запрос, как если бы это были данные.
Причина в том, что поставщики LINQ (например, LINQ to SQL) проверяют сам запрос, чтобы определить лучший способ преобразования выражений C # в запрос T-SQL. Поскольку дерево выражений позволяет вам смотреть на код как на данные, поставщик может это сделать.
Таким образом, основные различия между ними следующие:
Expression
- это дерево выражений , которое представляет исходный исходный код (он хранится в древовидной структуре данных, очень близкой к исходному коду C #). В этой форме вы можете анализировать исходный код, а такие инструменты, как LINQ to SQL, могут переводить дерево выражений (исходный код) на другие языки (например, SQL в случае LINQ to SQL, но вы также можете настроить таргетинг, например, JavaScript).
Func <...>
- это обычный делегат, который вы можете выполнить. В этом случае компилятор компилирует тело функции на промежуточный язык (IL), как при компиляции стандартного метода.
Стоит отметить, что Expression <..>
имеет метод Compile
, который компилирует выражение во время выполнения и генерирует Func <...>
, поэтому происходит преобразование из первого во вторую (с некоторыми затратами на производительность). Однако преобразования из второго в первый нет, потому что, как только вы получите IL, очень сложно (невозможно) восстановить исходный исходный код.
Func
создает исполняемую функцию.
Expression
создает дерево выражений, которое позволяет вам работать с кодом в функции как с данными.
Деревья выражений позволяют делать такие вещи, как LINQ to SQL и LINQ to XML, генерируя базовые вызовы из вашего кода .NET.
Выражение
- это представление функции, которую еще предстоит преобразовать в код. A Func <>
- это фактическая исполняемая функция. Использование первого позволяет вам превратить выражение в соответствующую функцию во время его вызова. Например, с LINQ to SQL это преобразует его в эквивалентный код для выполнения инструкции SQL и возврата указанного содержимого. С LINQ to objects он будет выполнять код на клиенте с помощью CLR. A Func <>
всегда выполняется в CLR - это исполняемый код.