Какова цель класса Expression?


мне интересно, в чем именно разница между обертыванием делегата внутри Expression<> и нет ?

Я вижу Expression<Foo> используется много с LinQ, но до сих пор я не нашел ни одной статьи, которая объясняет разницу между этим, и просто с помощью делегата.

например.

Func<int, bool> Is42 = (value) => value == 42;

и

Expression<Func<int, bool>> Is42 = (value) => value == 42;
6   51  

6 ответов:

сохраняя лямбда в качестве делегата, вы сохраняете конкретный экземпляр делегата, который выполняет некоторые действия. Он не может быть изменен, вы просто называете это. Если у вас есть свой делегат, у вас есть ограниченные возможности в проверке того, что он делает и что нет.

сохраняя лямбда-выражение, Вы сохраняете дерево выражений, которое представляет делегат. Его можно манипулировать, чтобы сделать другие вещи, такие как изменение его параметров, изменение тела и заставить его сделать что-то радикально отличающийся. Он даже может быть скомпилирован обратно в делегат, так что вы можете вызвать его, если хотите. Вы можете легко проверить выражение, чтобы увидеть, какие его параметры, что он делает и как он это делает. Это то, что поставщик запросов может использовать для понимания и перевода выражения на другой язык (например, написать SQL-запрос для соответствующего дерева выражений).

также намного проще создать делегат динамически используя выражения, чем он испускает код. Вы можете думать о своем коде на более высоком уровне как о выражениях, которые очень похожи на то, как компилятор просматривает код вместо перехода на низкий уровень и рассматривает ваш код как инструкции IL.

таким образом, с выражением вы способны сделать гораздо больше, чем простой анонимный делегат. Хотя это не совсем бесплатно, производительность будет хитом, если вы запустите скомпилированные выражения по сравнению с обычным методом или анонимным делегатом. Но это не может быть проблемой, как и другие преимущества использования выражения могут быть важны для вас.

Func<> Это просто тип делегата. Выражение-это представление во время выполнения полного дерева операции, который, при необходимости, может быть скомпилирован во время выполнения в делегат. Именно это дерево анализируется парсерами выражений, такими как Linq-to-SQL, для создания операторов SQL или других умных вещей. При назначении лямбда-выражения типу компилятор генерирует это дерево выражений, а также обычный код IL. подробнее о деревьях выражений.

чтобы проиллюстрировать другие ответы, если вы скомпилируете эти 2 выражения и посмотрите на сгенерированный компилятором код, это я то, что вы увидите:

Func<int, bool> Is42 = (value) => value == 42;

Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42);


Expression<Func<int, bool>> Is42 = (value) => value == 42;

ParameterExpression[] parameterExpressionArray;
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value");
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression });

предоставляет базовый класс, из которого представляют классы получаются узлы дерева выражений.

System.Linq.Expressions.BinaryExpression
System.Linq.Expressions.BlockExpression
System.Linq.Expressions.ConditionalExpression
System.Linq.Expressions.ConstantExpression
System.Linq.Expressions.DebugInfoExpression
System.Linq.Expressions.DefaultExpression
System.Linq.Expressions.DynamicExpression
System.Linq.Expressions.GotoExpression
System.Linq.Expressions.IndexExpression
System.Linq.Expressions.InvocationExpression
System.Linq.Expressions.LabelExpression
System.Linq.Expressions.LambdaExpression
System.Linq.Expressions.ListInitExpression
System.Linq.Expressions.LoopExpression
System.Linq.Expressions.MemberExpression
System.Linq.Expressions.MemberInitExpression
System.Linq.Expressions.MethodCallExpression
System.Linq.Expressions.NewArrayExpression
System.Linq.Expressions.NewExpression
System.Linq.Expressions.ParameterExpression
System.Linq.Expressions.RuntimeVariablesExpression
System.Linq.Expressions.SwitchExpression
System.Linq.Expressions.TryExpression
System.Linq.Expressions.TypeBinaryExpression
System.Linq.Expressions.UnaryExpression

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

дерево выражений представляет выражение linq, которое можно проанализировать и, например, превратить в SQL-запрос.

Выражение Деревьев позволяет проверить код внутри выражения, в вашем коде.

например, если вы передали это выражение:o => o.Name ваш код может найти то, что Name свойство было доступно внутри выражения.

к тому, что написал другой (это совершенно правильно), я добавлю это через