Разница между выражением <Func <>> и Func <>

В качестве примера, почему большинство операторов LINQ принимают Expression<Func<TSource>> и его эквивалент Func<TSource>?

Какая польза/причина использования универсального класса Expression вместо прямого синтаксиса лямбда?

Ответ 1

Используя Expression<T>, вы явно создаете дерево выражений - это означает, что вы можете иметь дело с кодом, составляющим запрос, как будто это были данные.

Причиной этого является то, что поставщики LINQ (например, LINQ to SQL) проверяют сам запрос, чтобы определить лучший способ перевода выражений С# в запрос T-SQL. Поскольку дерево выражений позволяет вам смотреть на код как данные, поставщик может это сделать.

Ответ 2

Итак, основные различия между ними следующие:

  • Expression<Func<...>> - это дерево выражений, которое представляет исходный исходный код (оно хранится в древовидной структуре данных, которая очень близка к исходному С# -коду). В этой форме вы можете анализировать исходный код, и такие инструменты, как LINQ to SQL, могут переводить дерево выражений (исходный код) на другие языки (например, SQL в случае LINQ to SQL, но вы также можете настроить таргетинг, например, на JavaScript).

  • Func<...> - обычный делегат, который вы можете выполнить. В этом случае компилятор компилирует тело функции на промежуточный язык (IL) так же, как при компиляции стандартного метода.

Стоит отметить, что Expression<..> имеет метод Compile, который компилирует выражение во время выполнения и генерирует Func<...>, поэтому происходит переход от первого ко второму (с некоторой производительностью). Однако переход от второго к первому отсутствует, потому что, как только вы получаете IL, очень сложно (невозможно) восстановить исходный исходный код.

Ответ 3

Func<T> создает исполняемую функцию.

Expression<Func<T>> создает дерево выражений, которое позволяет работать с кодом в функции как данные.

Деревья выражений позволяют делать такие вещи, как LINQ to SQL и LINQ to XML, генерируя базовые вызовы из вашего .NET-кода.

Ответ 4

An Expression<Func<>> - это представление функции, которая еще не превращена в код. A Func<> является фактической исполняемой функцией. Использование первого позволяет превратить выражение в соответствующую функцию в момент его вызова. Например, с LINQ to SQL это преобразует его в эквивалентный код для выполнения инструкции SQL и возвращает указанное содержимое. С LINQ к объектам он будет выполнять код на клиенте с использованием CLR. A Func<> всегда выполняется в CLR - это исполняемый код.