Подтвердить что ты не робот

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

Мне интересно, какая именно разница между переносом делегата внутри Expression<> и не?

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

например.

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

против.

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

Ответ 1

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

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

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

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

Ответ 2

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

Ответ 3

Чтобы проиллюстрировать другие ответы, если вы скомпилируете эти 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 });

Ответ 4

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

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-запрос.

Ответ 5

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

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

Ответ 6

То, что написал другой (что совершенно верно), я добавлю, что через класс Expression вы можете создавать новые методы во время выполнения. Есть некоторые ограничения. Не все, что вы можете сделать на С#, можно сделать в дереве Expression (по крайней мере, в .NET 3.5. С .NET 4.0 они добавили большое количество возможных типов Expression "). Использование этого может быть (например), чтобы создать динамический запрос и передать его LINQ-to-SQL или сделать некоторую фильтрацию на основе ввода пользователя... (вы всегда можете сделать это с помощью CodeDom, если все, что вам нужно был динамическим методом, несовместимым с LINQ-to-SQL, но испускать непосредственно IL-код довольно сложно:-))