繁体   English   中英

用于Enumerable和Queryable扩展方法的Lambda表达式参数

[英]Lambda expression arguments for Enumerable and Queryable extension methods

Lambda表达式是一个匿名方法,在后台它是一个委托,因此我可以执行以下操作:

 delegate bool Foo(int x);

 Foo bar = x => x == 1;

将此委托传递给Enumerable扩展方法是很有意义的,因为典型的期望参数是Func ,它是委托的简写:

 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

但是,我不清楚如何将委托传递给像这样的Queryable扩展方法:

 public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

此方法需要一个Expression<TDelegate>参数,但是传入lambda表达式是完全合法的。 将lambda表达式Expression<TDelegate>转换为Expression<TDelegate>以便可以被使用的机制是什么?

我对Queryable方法建立了表达式树以供提供程序进行解析的事实非常熟悉,我只是对这一方面感到好奇,这一方面对我而言并不立即显而易见。

更新

我对我的无知越来越不了解。 Lambda表达式不是委托,但可用于创建委托或表达式:

 Expression<Func<int, bool>> foo = c => c == 1;

编译器是否根据上下文推断类型? 我猜测一定是这样,因为这是不合法的:

var foo = c => c == 1;

在规范中对此进行了描述:

4.6表达式树类型

如果存在从lambda表达式到委托类型D的转换,则也存在到表达式树类型Expression<D> 将lambda表达式转换为委托类型会生成引用了lambda表达式的可执行代码的委托,而转换为表达式树类型则会创建lambda表达式的表达式树表示形式。 表达式树是lambda表达式的有效内存数据表示形式,并使lambda表达式的结构透明且显式

因此,存在从lambda到兼容的表达式树类型的转换,并且编译器发出等效的表达式树而不是创建委托。

很简单,您做不到。 但是,为了使IQueryable方法有用,VS2008及更高版本包含了一个聪明的编译器技巧。 可以将作为单个语句的lambda expression分配给delegateExpression<TDelegate> 编译器通常会提升表达式并创建一个方法。

但是对于一个Expression<TDelegate>的赋值,它将语句分解为它们的语法含义,并将其转变为一个表达式树。

例如

Func<int,int> func = x=>x*x;
Expression<Func<int,int>> expression = x=>x*x;

第一个可能会变成一个带有乱码名称的静态方法,例如:

private static int <B012>SomeMethod(int x){
   return x*x;
}

其中,第二条语句将转换为:

ParameterExpression paramX = Expression.Parameter(typeof(int));
Expression<Func<int,int>> expression = Expression.Lambda<Func<int,int>>(
     Expression.Multiply(paramX,paramX),paramX);

但是你不能做:

expression = func;

这是无效的,因为funcdelegate 您可以执行以下操作:

func=expression.Compile()

将表达式编译成函子。

**请注意,建议的转换可能不是100%正确的。

他们这样做的原因是允许LINQ-to-Objects(基本上是其他语言的Map / Reduce)共享与LINQ-To-Providers相同的友好语法。 因此,您可以编写一条具有相同含义的语句,但可以更改过滤和转换发生的位置。 GetEmployees().Where(e=>e.LastName=="Smith")可以读取相同内容,但从理论上讲可以描述在此框或数据库上进行过滤,或者解析xml文件或任意数量的各种各样的东西。

我认为这与如何在IQueryable上构建查询有关。 该方法需要一个表达式树,因为它可以在内部查看并进行结构化,以匹配更优化(可能)的查询或更紧密地映射到基础数据源。 因此,简单地传递一个Func仅允许执行,而Expression < Func >允许可以观察和执行的表达式树。

另外,可能更接近回答您的确切问题, 请查看此SO发布

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM