В качестве примера, почему большинство операторов 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 - это исполняемый код.