#c# #delegates #lambda #expression-trees
#c# #делегирует #лямбда #деревья выражений
Вопрос:
Оба приведенных ниже фрагмента выдают один и тот же результат. Я понимаю, как Func инкапсулирует метод с одним параметром и возвращает значение bool. И вы можете либо назначить ему метод, анонимный метод, либо лямбда-выражение.
Func<int, bool> deleg = i => i < 5;
Console.WriteLine("deleg(4) = {0}", deleg(4));
Ниже используются деревья выражений, которые я еще не до конца понимаю. Почему я должен хотеть сделать это таким образом? Является ли это более гибким, какое преимущество это дает мне?
System.Linq.Expressions.Expression<Func<int, bool>> expr = i => i < 5;
Func<int, bool> deleg2 = expr.Compile();
Console.WriteLine("deleg2(4) = {0}", deleg2(4));
Ответ №1:
По сути, дерево выражений — это тело лямбда-выражения, которое позволяет вам
- проанализируйте выражение (так сказать, посмотрите, что в нем)
- манипулируйте выражением (упрощайте, расширяйте (например, добавляйте новые функциональные возможности или модифицируйте для работы с разными элементами).
Как только вы Compile()
задаете выражение, это просто еще один делегат, который вы можете только вызывать, но не проверять или изменять.
Всякий раз, когда вы хотите
- создавайте выражения динамически (я имею в виду: конструируйте, а не распределяйте)
- динамически работать с выражениями
Function<>
типов недостаточно.
Ответ №2:
Суть деревьев выражений в том, что с ними можно делать больше, чем просто компилировать их в функцию. Вы можете проверять их, изменять и компилировать во что-то другое, кроме функций .net.
Например, Linq2SQL компилирует деревья выражений в код SQL. Вы не смогли бы сделать это с помощью простого .сетевая функция.
Комментарии:
1. как вы их проверяете? как называется этот процесс? примеры?
2. @codecompleting: использование методов и свойств класса Expression и его подклассов . Вы можете увидеть небольшой пример, например, в этой статье .
Ответ №3:
В вашем первом примере вы просто «жестко запрограммировали» тело функции и назначили его делегату.
Во втором примере присваивание создает дерево выражений, которое является объектной моделью, отображающей ваш код в структуре данных в памяти.
Преимущество заключается в том, что вы можете изменять и проверять эту структуру данных.
LINQ2SQL, например, использует эту технику для перевода ваших выражений на другой язык, называемый SQL.
Ответ №4:
Деревья выражений — это обычные структуры данных в памяти, которые можно просматривать программно, и результатом такого обхода может быть что-то вроде запроса, который вы хотели бы отправить в базу данных. Прочитайте больше о ExpressionVisitor
классе, чтобы увидеть, как это делается.
С другой стороны, скомпилированная функция — это не что иное, как последовательность кода CIL. Вы все еще можете проверить это программно, но вы проверяете не определение, а скорее — его вывод компилятором.