Expression<Func<>> vs Func<>

Introduction

An expression is a sequence of operands and operators that can be evaluated to a single value or method or object or namespace. It can consist of literal values, method invocations, names of variables, names of methods, method parameters or types. Expression can vary from very simple to very complex. The following is an example of Expression:

(n<5) && (n>6)

The manner expression values are evaluated follows general operator precedence and associativity rules. Expression trees represent code as a tree-like data structure, where each node is an expression. Expression trees are used in LINQ and in the Dynamic Language Runtime (DLR).

You can create an expression tree based on an anonymous lambda expression or you can create expression trees manually.

Creation

You can create an Expression Tree as follows:

Expression<Func<int, bool>> myExp = n => n > 0;

I have previously posted an article on Func delegates. Well it is a normal multicast delegate. Now the question arises, what is the difference between Expression<Func<>> and normal Func<>. We need to really understand the difference to write better queries when working with Entity Framework.

Difference between Func<> and Expression<Func<>>

There are many differences. Developers don't know whether they should use a Func<> or an Expression<Func<>> with the Entity Framework and LINQ. If you see the IQueryable interface, many methods expect an Expression as parameters. Then what is the real use? Let us see in this article.

If you see the definitions, conceptually they are completely different. Func<T> denotes a delegate that is pretty much a pointer to a method and Expression<Func<T>> denotes a tree data structure for a lambda expression. I think it explains well about when to use it. If you want to treat lambda expressions as expression trees and look inside them and don't want to execute them, you can use it as Expression Trees. For example, LINQ to SQL gets the expression and converts it to the equivalent SQL statement and submits it to the server rather than executing the lambda. Expression trees can also be constructed using API syntax. I haven't used it ever, but if you are interested then you can go to MSDN and can see some example. My point is the Entity Framework's fluent interface for constructing SQL queries is based on IQueryables, not IEnumerables.

Implementation

Let us see the Where extension method for Enumerables as in the following:

  1. public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate)  
  2. {  
  3.     return (IEnumerable<TSource>) new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);  
  4. }  
You can clearly see this extension method expects a Func delegate as the parameter. Now if we see the Queryable implementation:
  1. public static IQueryable<TSource> Where<TSource>( this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)  
  2. {  
  3.     return source.Provider.CreateQuery<TSource>(  
  4.     Expression.Call(  
  5.     null,   
  6.     ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(  
  7.         new Type[] { typeof(TSource) }),   
  8.         new Expression[] { source.Expression, Expression.Quote(predicate) }));  
  9. }  
See, it expects the Expression as the parameter. Now the question is, which one is preferable?

Usage

Well the usage differs. Though my personal preference is to use IEnumerable wherever possible since it works with in-memory entities. So it doesn't hit the database as an IQueryable does. But again the choice comes with applying different filters. You might not get the expected results in situations. Let us see an example to describe it.

Suppose one of our Entities is Employee that has the columns EmpNo, EmpName and EmpSal. Now create an extension method as:
  1. public static IEnumerable<Employee> GetEmployees(this IEnumerable<Employee> source, Func<Employee, bool> predicate,int number)  
  2. {  
  3.     return source.Where(predicate)  
  4.         .OrderBy(s => s.EmpSal)  
  5.         .Take(number);  
  6. }  
The same thing can also be done using IQueryable as follows:
  1. public static IQueryable<Employee> GetEmployees(this IQueryable<Employee> source,Expression< Func<Employee, bool>> predicate, int number)  
  2. {  
  3.     return source.Where(predicate)  
  4.         .OrderBy(s => s.EmpSal)  
  5.         .Take(number);  
  6. }  
If you use both the program and see what the query returns, you will observe that the Take(number) is ignored in IEnumerable but included in IQueryable since IEnumerable will first load the data in memory and then will apply the filter, but IQueryable will apply all the filters and then execute the query.

Looking deep into the difference

You have seen the usage and hopefully have gotten the idea of when to use IQueryable and its benefits. Let's see in depth what will happen when in the IEnumerable extension we pass an Func<> instead of Expression<Func<>>.

If we modify our method as in the following:
  1. public static IEnumerable<Employee> GetEmployees(EmployeeDataContext source,Expression<Func<Employee, bool>> predicate, int number)  
  2. {  
  3.     return source.Employee.Where(predicate)  
  4.         .OrderBy(s => s.EmpSal)  
  5.         .Take(number);  
  6. }  
Now you will see all the filters are applied to the query. So why did the first version ignore the WHERE, ORDERBY and TOP clauses? Here is why: 
  1. IQueryable's Where method expects an Expression<Func<,>>. But the parameter is only Func<>.

  2. IQueryable<> inherits from IEnumerable<> . Since IQueryable<> does have a Where method that takes a Func<> so the code uses the base Where.

  3. So finally, the query executes on IEnumerable<> that doesn't have anything to do with SQL and served the complete table from the memory.
My Opinion

Well I personally use it in various ways. For a larger table I used to load it first in memory and then apply the filters afterwards like list.where(s=>s.EmpName.StartsWith(“L”)); list.Take(3). But again for the generalized version I used the extension method. IEnumerable gives performance benefits since it doesn't hit the database, rather it works with in-memory collections.

I hope this helps. 


Similar Articles