Search code examples
c#linqexpressionpredicatebuilder

Is there a benefit in using Expressions to build dynamic LINQ queries compared to chaining Funcs if I am not using SQL?


I need to build a dynamic query that can query a large list of objects and get the objects which satisfy a complex predicate known at runtime. I know I want to do it upfront and pass it into the collection to filter on, rather than create some complex switch case on the collection itself.

Everything points me to Expressions and Predicate Builder, which I'm happy to use to chain together expressions in a loop like:

Expression<Func<MyObject, bool>> query = PredicateBuilder.True<MyObject>();
query = query.And(x => x.Field == passedInSearchCriterion)

but I could also do that with:

Func<MyObject, bool> query = x => true;
query = x => query(x) && (x => x.Field == passedInSearchCriterion)

I know the first is better in the case of LINQ to SQL converting it to SQL to execute in the database etc when given to entity framework or something.

But say they were both run locally, not in a database, on a large list, is there any performance difference then in terms of how the resulting function is executed?


Solution

  • I know the first is better because of LINQ to SQL converting it to SQL to execute in the database etc when given to entity framework or something.

    No, you don't "know" it's better because you don't understand the difference between expressions and delegates.

    That main difference is that expressions are effectively descriptions of a piece of code, and can be inspected to find out information like parameter names - this is why ORMs use them, to map POCOs to SQL columns - while delegates are nothing more than pointers to a method to be executed. As such, there are optimizations the C# compiler can perform on delegates, which it cannot do for expressions. Further details here.

    So yes, there will be a performance difference, almost certainly in favour of delegates. Whether that difference is quantifiable and/or relevant to your use-case is something only you can determine via benchmarks.

    But any performance difference is irrelevant anyway, because you don't need expressions for your use-case. Just use delegates, which will always be faster.