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

Tom*_*m67 8 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<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); 
Run Code Online (Sandbox Code Playgroud)

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

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

Expression<Func<Person,int>> lambda3 = x => x.AProp;
Expression<Func<Person,bool>> lambda4 = x => x.BProp;
Run Code Online (Sandbox Code Playgroud)

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

var query = source.Where(x => x.BProp).OrderBy(x => x.AProp);
Run Code Online (Sandbox Code Playgroud)

要么

var query = from x in source where x.BProp order by x.AProp select x;
Run Code Online (Sandbox Code Playgroud)

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

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

Eri*_*ert 8

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

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

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

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

x => Foo(x);
y => Bar(y);
Run Code Online (Sandbox Code Playgroud)

并从他们建立第三,说:

(x,y) => Foo(x) && Bar(y);
Run Code Online (Sandbox Code Playgroud)

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

(x,x) => Foo(x) && Bar(x);  // Huh?
Run Code Online (Sandbox Code Playgroud)

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

x => Foo(x);
x => Bar(x);
Run Code Online (Sandbox Code Playgroud)

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

x => Foo(x) && Bar(x);
Run Code Online (Sandbox Code Playgroud)

因为那时你就不会需要重写任何东西.

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