Problem
I’m familiar with lambdas, as well as the Func and Action delegates. But it’s the expressions that get me.
In what situations would you prefer to employ an ExpressionFuncT>> over a regular FuncT>?
Asked by Richard Nagle
Solution #1
When you wish to treat lambda expressions like expression trees and inspect them rather than execute them. For example, LINQ to SQL takes an expression and turns it to a SQL query before sending it to the server (rather than executing the lambda).
In terms of concept, ExpressionFuncT>> is not the same as FuncT>. ExpressionFuncT>> denotes a tree data structure for a lambda expression, and FuncT>> denotes a delegate, which is essentially a reference to a method. Rather of doing the action, this tree structure describes what a lambda expression does. It essentially stores information about the composition of expressions, variables, method calls, and so on (for example, this lambda is some constant + some argument). This description may be used to turn it to an actual method (using Expression.Compile) or to do other things (like the LINQ to SQL example). It’s entirely a compile-time decision to treat lambdas as anonymous procedures and expression trees.
Func<int> myFunc = () => 10; // similar to: int myAnonMethod() { return 10; }
will effectively compile to an IL method that gets nothing and returns 10.
Expression<Func<int>> myExpression = () => 10;
will be transformed into a data structure describing an expression with no parameters that returns the value 10:
larger image
While they appear to be the same at compile time, the compiler produces a completely different result.
Answered by mmx
Solution #2
I’m including an answer for noobs because these answers appeared to be beyond my comprehension until I discovered how simple they are. It’s sometimes your anticipation that something is complicated that prevents you from ‘wrapping your head around it.’
I didn’t need to know the distinction until I ran into a particularly vexing ‘fault’ while trying to utilize LINQ-to-SQL in a general way:
public IEnumerable<T> Get(Func<T, bool> conditionLambda){
using(var db = new DbContext()){
return db.Set<T>.Where(conditionLambda);
}
}
This ran fine until I started getting OutofMemoryExceptions when I tried to use it with larger datasets. Setting breakpoints inside the lambda revealed that it was iterating through each row in my table one at a time, looking for matches to my lambda condition. For a long time, I couldn’t figure out why it was treating my data table like a large IEnumerable instead of executing LINQ-to-SQL like it should. In my LINQ-to-MongoDb equivalent, it was also performing the same thing.
The solution was to change FuncT, bool> to ExpressionFuncT, bool>>, so I looked up why it needed an Expression instead of a Func and found this.
a delegate into a set of information about itself As a result, a => a + 1 becomes “There’s an int a on the left side. You increase it by one on the right side.” That is all there is to it. You are now free to return home. It’s obviously more structured than that, but an expression tree is essentially that—nothing to get your head around.
Knowing this, it’s evident why LINQ-to-SQL requires an Expression and why a Func isn’t sufficient. Func doesn’t include a method to delve deeper into itself, to discover how to translate it into a SQL/MongoDb/other query. You can’t tell if it’s doing addition, multiplication, or subtraction because you can’t see it. All you have to do now is run it. Expression, on the other hand, permits you to peer inside the delegate’s mind and see whatever it desires. This allows you to convert the delegate into anything you wish, such as a SQL query. My DbContext was blind to the contents of the lambda expression, therefore Func didn’t work. It couldn’t convert the lambda expression to SQL because of this; nevertheless, it did the next best thing and
At John Peter’s request, I’ll expand on my previous sentence:
IQueryable extends IEnumerable, therefore Where() and other IEnumerable methods now have Expression overloads. When you pass an Expression, you’ll get an IQueryable as a result, but when you pass a Func, you’ll get an IEnumerable as a result. In other words, you’ve changed your dataset into a list to be iterated rather than a query without even realizing it. It’s difficult to tell the difference until you look closely at the signatures.
Answered by Chad Hedgcock
Solution #3
IQueryable providers like LINQ to Entities can ‘digest’ what you supply in an Expression, but will ignore what you pass in a Func. This is an incredibly significant aspect when choosing between Expression and Func. I’ve written two blog posts on it:
More on Entity Framework’s Expression vs. Funcs and Falling in Love with LINQ – Part 7: Expressions and Funcs (the last section)
Answered by LSpencer777
Solution #4
Krzysztof Cwalina’s book (Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable.NET Libraries) provides a deeper philosophical approach.
For the non-image version, make the following changes:
Answered by Oğuzhan Soykan
Solution #5
I’d like to provide some clarifications regarding the differences between FuncT> and ExpressionFuncT>>:
LINQ: FuncT> vs. ExpressionFuncT>> is an essay that goes over the details with code examples.
I hope you find it useful.
Answered by Olexander Ivanitskyi
Post is based on https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct