LINQ lambda表达式参数应该在第二个lambda中重用吗?

在这个问题之后,我想知道lambda参数表达式实例的重用是否应该被认为是好的还是坏的?

我有时会得到一个完整的LINQ表达式树,其中同一个lambda参数实例在第二个非生成的lambda中正确使用:

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

因此,同一lambda参数实例lparam的声明对于lambda1和lambda2都是正确的。

只是这个共享的lambda参数实例强制IQueryProvider实现不基于纯lambda参数引用关联其他全局含义,因为在处理不同的lambda期间可能需要不同地解释相同的参数。 另外,你不会通过使用从LINQ获得这种表达式树(或者我应该说图形?)

 Expression<Func> lambda3 = x => x.AProp; Expression<Func> lambda4 = x => x.BProp; 

因为两个lambda表达式都有(Person x)的不同参数实例。 同样的道理

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

要么

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

它还使表达式树成为一个图形。

这种参数实例的重用方式是好还是坏? 到目前为止,我还没有从当局那里找到明确的答案。

我不会在两个不相交的lambda之间共享一个参数对象。

首先,我们不要在这里制造虚假经济。 物品很便宜,你不会制造十万件。 (如果你是,你可能有更大的问题需要解决。)

其次,正如您所注意到的,在不相关的lambda中共享引用相同的参数对象意味着需要分析这些lambda表达式树的代码来理解参数对象在不同的​​上下文中具有不同的含义。 这似乎是一个等待发生的错误。

第三,有人想象有一天你可能想要两个表达式树:

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

并从他们建立第三,说:

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

如果x和y实际上都是相同的参数对象,那么你手上就有问题:

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

另一方面,StriplingWarrior的答案指出,如果你有

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

然后将它们组合起来更容易

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

因为那时你不需要重写任何东西。

基本上,这似乎是一个冒险的举措,没有真正令人信服的上行空间,为什么呢?

您需要考虑您的用例。 这些lambdas将来如何结合起来呢?

例如,您是否想要使用OR运算组合两个lambda?

 Expression> lambda1 = p => !p.IsDeleted; Expression> lambda2 = p => p.DomainId == 1; // How do I get (p => !p.IsDeleted || p.DomainId == 1)? 

如果是这样,就像这样加入它们更容易:

 Expression.Lambda>( Expression.OrElse(lambda1.Body, lambda2.Body), lambda1.Parameters[0]); 

如果它们都具有相同的参数表达式对象,则上述代码可以正常工作。 如果他们不这样做,突然你必须遍历lambda2的整个树,创建一个新的表达式树,用于替换第一个表达式中的参数。 它可以完成,并且我已经编写了一些实用程序方法,以便在我必须执行此类操作时轻松实现,但是如果您能够确定这是用例的类型,那么您可能会遇到首先使用相同的参数让自己的生活变得更简单。

另一方面,如果你要以一种参数需要在一个更大的lambda表达式中扮演不同角色的方式组合lambdas,正如Eric指出的那样,那么你将需要那些参数不同。