Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should LINQ lambda expression parameters be reused in a second lambda?

Tags:

c#

lambda

linq

Following this question I would like to know if the reuse of lambda parameter expression instances should be considered good or bad?

I sometimes get a complete LINQ expression tree where the same lambda parameter instance is local correctly used in a second, nonnested lambda:

// class Person { public int AProp { get; set; } public bool BProp { get; set; }}
var lparam = Expression.Parameter(typeof(Person),"x");
var lambda1 = (Expression<Func<Person,int>>)Expression.Lambda(Expression.Property(lparam, "AProp"), lparam);
var lambda2 = (Expression<Func<Person,bool>>)Expression.Lambda(Expression.Property(lparam, "BProp"), lparam);
var source = (new Person[0]).AsQueryable();
var query = source.Where(lambda2).OrderBy(lambda1); 

So the declaration of the same lambda parameter instance lparam is correct for both lambda1 and lambda2.

It is just that this shared lambda parameter instance forces IQueryProvider implementations to not associate additional global meaning based on the pure lambda parameter reference, as the same parameter could need to be interpreted differently during processing of a different lambda. Also, you will not get this kind of expression tree (or should I say graph?) from LINQ by using

Expression<Func<Person,int>> lambda3 = x => x.AProp;
Expression<Func<Person,bool>> lambda4 = x => x.BProp;

because there will be different parameter instances of (Person x) for both lambda expressions. The same goes for

var query = source.Where(x => x.BProp).OrderBy(x => x.AProp);

or

var query = from x in source where x.BProp order by x.AProp select x;

It also makes the expression tree to be rather a graph.

Is that style of reuse of parameter instances considered good or bad? So far, I have not found a clear answer to this from the authorities.

like image 864
Tom67 Avatar asked Sep 20 '13 07:09

Tom67


People also ask

What is difference between LINQ and lambda expression?

Language Integrated Query (LINQ) is feature of Visual Studio that gives you the capabilities yo query on the language syntax of C#, so you will get SQL kind of queries. And Lambda expression is an anonymous function and is more of a like delegate type.

What is lambda expression in LINQ?

A lambda expression is a convenient way of defining an anonymous (unnamed) function that can be passed around as a variable or as a parameter to a method call. Many LINQ methods take a function (called a delegate) as a parameter.

Which is faster LINQ or lambda?

Lambda will have an advantage since it creates a delegate and by using the delagte you can just pass the input paremeters and get the result for the different input parameters. You need not write different queries for different criteria as well.

Which is better lambda or LINQ?

So performance-wise, there's no difference whatsoever between the two. Which one you should use is mostly personal preference, many people prefer lambda expressions because they're shorter and more concise, but personally I prefer the query syntax having worked extensively with SQL.


1 Answers

I would not share a parameter object between two disjoint lambdas.

First, let's not make false economies here. Objects are cheap and you are not going to be making a hundred thousand of these. (And if you are, you probably have larger problems to solve.)

Second, as you note, sharing referentially identical parameter objects across unrelated lambdas means that code which analyzes those lambda expression trees is required to understand that the parameter object has a different meaning in different contexts. That seems like a bug waiting to happen.

Third, one imagines that someday you might want to take two expression trees:

x => Foo(x);
y => Bar(y);

and from them build a third, say:

(x,y) => Foo(x) && Bar(y);

If x and y are actually both the same parameter object then you have a problem on your hands:

(x,x) => Foo(x) && Bar(x);  // Huh?

On the other side, StriplingWarrior's answer points out that if you have

x => Foo(x);
x => Bar(x);

then it is easier to combine them as

x => Foo(x) && Bar(x);

because then you do not need to rewrite anything.

Basically, it just seems like a risky move with no truly compelling upside, so why do it?

like image 200
Eric Lippert Avatar answered Nov 14 '22 23:11

Eric Lippert