C# LINQ lambda表达式参数是否应该在第二个lambda中重用?

C# LINQ lambda表达式参数是否应该在第二个lambda中重用?,c#,linq,lambda,C#,Linq,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<Fu

下面我想知道重用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<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); 

它还使表达式树更像一个图


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

我不会在两个不相交的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);
因为这样你就不需要重写任何东西了


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

< P>你需要考虑你的用例。这些lambda将来如何组合

例如,是否要使用OR操作组合两个lambda

Expression<Func<Person, bool>> lambda1 = p => !p.IsDeleted;
Expression<Func<Person, bool>> lambda2 = p => p.DomainId == 1;
// How do I get (p => !p.IsDeleted || p.DomainId == 1)?
表达式lambda1=p=>!p、 被删除;
表达式lambda2=p=>p.DomainId==1;
//如何获取(p=>!p.IsDeleted | | p.DomainId==1)?
如果是这样,就更容易像这样加入他们:

Expression.Lambda<Func<Person, bool>>(
    Expression.OrElse(lambda1.Body, lambda2.Body), 
    lambda1.Parameters[0]);
Expression.Lambda(
表达式.OrElse(lambda1.Body,lambda2.Body),
lambda1.参数[0]);
如果上面的代码都具有相同的参数表达式对象,那么它们就可以正常工作。如果没有,您必须遍历
lambda2
的整个树,创建一个新的表达式树,用第一个表达式中的参数替换该参数。这是可以做到的,我已经写了一些实用方法,当我不得不做这样的事情时,可以让它变得简单,但是如果你能确定这是你将遇到的用例类型,那么你最好首先使用相同的参数,让你的生活更简单


另一方面,如Eric所指出的,如果要以参数需要在更大的lambda表达式中扮演不同角色的方式组合lambda,那么就需要这些参数有所不同。

从逻辑上讲,我看不出参数重用有什么意义。我知道通过重用lambda而不是制作一堆相同的lambda,我已经发现了显著的性能提升,但不知道参数重用。我建议进行性能测试。如果你想办法让它们循环使用,这可能是个问题。@Tom67:这就是为什么最好以问题的形式提问,而不是以评论的形式提问。我从来没有在评论中提到过。非常感谢!我曾希望/预料到这个答案,现在我可以更好地与这些树木的生产者争论。
x => Foo(x) && Bar(x);
Expression<Func<Person, bool>> lambda1 = p => !p.IsDeleted;
Expression<Func<Person, bool>> lambda2 = p => p.DomainId == 1;
// How do I get (p => !p.IsDeleted || p.DomainId == 1)?
Expression.Lambda<Func<Person, bool>>(
    Expression.OrElse(lambda1.Body, lambda2.Body), 
    lambda1.Parameters[0]);