Какова цель класса Expression?
мне интересно, в чем именно разница между обертыванием делегата внутри Expression<>
и нет ?
Я вижу Expression<Foo>
используется много с LinQ, но до сих пор я не нашел ни одной статьи, которая объясняет разницу между этим, и просто с помощью делегата.
например.
Func<int, bool> Is42 = (value) => value == 42;
и
Expression<Func<int, bool>> Is42 = (value) => value == 42;
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
свойство было доступно внутри выражения.