LINQ的Expression.Quote方法的目的是什么?

49

MSDN文档称:

Expression.Quote

方法创建一个表示类型为Expression的常量值的表达式的UnaryExpression。

我已经成功地使用Expression类手动构建用于LINQ查询中的谓词表达式,但从未遇到需要使用Expression.Quote的情况。

什么时候以及为什么要使用它?从我看到带有它们的LINQ表达式来看,它们似乎只是在不添加任何价值的情况下包装现有表达式。

引用(Quote)方法/节点的目的是什么?


当您使用Expression.Call构造MethodCallExpression时,任何作为参数的lambda表达式(LambdaExpression/Expression<TDelegate>)都必须在传入之前使用Expression.Quote进行包装。这是真的吗?在使用.Net 4.5时,我能够成功地传递裸的Expression<Func<>>,而不需要先用Expression.Quote()引用它们。 - Daniel Yankowsky
如果你的参数类型是Func<>,那么这就是你所需要的全部。但对于许多LINQ IQueryable<T>扩展方法而言,参数类型实际上是Expression<Func<>>,在这种情况下,你将需要使用Expression.Quote。我还没有尝试在.NET 4.5中进行这个操作,但我认为它应该是一样的。在写作时,我可能正在使用.NET 3.5。 - John Mills
1个回答

32

Expression.Quote指定一个lambda表达式应该被视为一个表达式树而不是函数,并且它在其操作数上引入了闭包语义。

当您使用Expression.Call构建MethodCallExpression时,任何作为lambda表达式(LambdaExpression/Expression<TDelegate>)的参数必须在传递之前使用Expression.Quote进行包装。

所以对于类型为Expression<Func<bool>>的参数,当您创建如下实例时:() => true,表达式的Type属性将是Func<bool>,而表达式的类型(调用GetType)将是Expression<Func<bool>>

因此,要获取具有正确Type属性值的Expression,请将lambda表达式传递到Expression.Quote中,并将其作为参数传递给Expression.Call

我通过反射查看了Expression.Quote,虽然唯一的参数类型是Expression,但它必须派生自LambdaExpression,并且在方法内部进行了检查。出于兴趣,有没有人知道为什么MS不直接使参数类型为LambdaExpression

正如StevenH所指出的那样,Expression.Quote用于实现LINQ查询提供程序。 Queryable上的所有接受lambda表达式的方法(例如WhereOrderByGroupBy等)在内部使用Expression.Call构造MethodCallExpression并使用Expression.Quote调用包装lambda表达式参数。

有关Expression.Quote的更详细解释,请阅读这个答案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接