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