Func<T> vs. Expression<Func<T>> in LINQ

This content is more than 3 years old. Please read this keeping its age in mind.

Linq is fantastic in that it provides a consistent syntax to query all sorts of data sources from in-memory collections, SQL databases, XML files, even external APIs. One of its strengths is that you can write a Linq provider for any data source you want to support.

Most people know about the “not obvious until it’s obvious” difference between IEnumerable<T> and IQueryable<T> - one represents an in-memory collection and one represents a query which will be executed at some point against a data source. Both have an almost identical set of LINQ extensions, except the IEnumerable<T> extensions accept Func<T> and the IQueryable<T> extensions accept Expression<Func<T>>.

Why?? We’ll go over that next, the reason as it turns out illustrates the difference between Func<T> and Expression<Func<T>> really well.

Func<T> vs. Expression<Func<T>>

Go ahead - fire up Visual Studio and take a look at the method signatures of an IEnumerable and an IQueryable for the where linq extension.

  • The IEnumerable version: Where(Func<T, bool> predicate)
  • The IQueryable version: Where(Expression<Func<T, bool>> predicate)

Don’t worry if you haven’t noticed the differences, you call them with the exact same syntax.

  • IEnumberable version: .Where(x => x.property == "value")
  • IQueryable version: .Where(x => x.property == "value")

So why the difference in signature if they have the same syntax?

It boils down to the following difference

  • Func<T> is just a pointer to an ordinary delegate that has been compiled down to IL (intermediate language) just like any other C# code that you write. There is nothing special about it.

  • Expression<Func<T>> is a description of a function as an expression tree. It can be compiled to IL at run time that generates a Func<T> but it can also be translated to other languages e.g. SQL in LINQ to SQL.

You need an expression for IQueryable because we don’t know what we’re querying - the specific IQueryable implementation will translate the given expression into whatever language needed to access the data. E.g. SQL in LINQ to SQL, or a specific HTTP request for a REST API.

You don’t need an expression for IEnumerable as it’s just an in-memory collection that understands vanilla IL so we can save a whole bunch of overhead and throw compiled queries at it.

You can convert an Expression<Func<T>> to a Func<T> by calling the the Compile method that compiles the expression tree to IL - this is done at run-time so has a performance overhead compared to dealing with Func<T> directly. You cannot convert a Func<T> to an Expression<Func<T>> as you cannot reverse engineer IL to get the original source code back at run time. Not only is it very difficult to reverse engineer but compiling can be a lossy process full of performance tricks so it’s very hard/ impossible to get the exact source code back even if you were super determined.

Summary

Even if you skimmed the lot - all you really need to know is that Func<T, bool> is a pointer to a compiled delegate method and Expression<Func<T, bool>> is a description of a function that can be compiled to IL at runtime or translated into whatever language we have a provider for.

Noticed an error or omission? Please look at submitting a pull request.