LINQ中的表达式树是什么?

时间:2009-01-13 20:07:35

标签: linq

LINQ中的表达式树是什么?有人可以指向一个有代码和解释的资源吗?

1 个答案:

答案 0 :(得分:2)

表达式树是一棵树,其中所有节点都是Expression s(跟我一起)。

我不完全确定你是否询问表达式树的特定应用,所以这已经有点冗长了,但是应该知道它们可以被使用的一般方法。 MSDN有一些general programming concepts documentation for Expression Trees,并且总是有System.Linq.Expressions中实际类的文档。我相信当我第一次看表达式时我发现these Microsoft provided examples很有用,但我没记错。

您可能熟悉语法树的概念。例如,2 + 2通常在视觉上描绘为具有语法树:

  +
 / \
2   2

表达树在概念上非常相似。这是一个微笑的树,所有节点都是表达式。表达式2 + 2将由代码

表示
Expression.Add(Expression.Constant(2), Expression.Constant(2))

返回BinaryExpression并且是表达式树。


Lambda表达式

Lambda Expressions经常使用表达式(当它们被使用时)。

这是一个lambda语句或lambda块:

i => {return i * 2;}

这是一个lambda表达式:

i => i * 2

您可能习惯于看到上面的代码接下来的类型为Func

Func<int, int> timesTwo = i => i * 2;

但是这样做也是有效的:

 Expression<Func<int, int>> timesTwoExpression = i => i * 2;

在这种情况下,编译器将为表达式而不是委托发出表达式树。您可以稍后在其上调用Compile()以获取代理。

Func<int, int> timesTwo = timesTwoExpression.Compile()

但是,由于表达式尚未编译,因此可以对其进行检查和/或操作。例如,我可以检查表达式的主体并确认乘法常数实际上是两个。

Expression<Func<int, int>> timesTwoExpression = i => i*2;
Assert.True(timesTwoExpression.Body.NodeType == ExpressionType.Multiply);
Expression right = ((BinaryExpression) timesTwoExpression.Body).Right;
Assert.True( right.NodeType == ExpressionType.Constant);
Assert.AreEqual( ((ConstantExpression) right).Value, 2);

我个人使用了这个to get property/method namesprovide a null lift operator for chaining member calls,并且只在运行时知道类型时指定泛型类型的类型参数。注意:我不能保证这些链接问题的具体答案,我没有根据我写的代码检查它们;我提供它们仅供参考和示例。

这只允许访问Expression API的有限部分(您只能将它与Lambda表达式一起使用而不能用于Lambda语句),但它仍然非常有用。但是,这是一项高级功能,您的所有团队可能都不理解,因此负责任地使用。


LINQ查询的表达式

表达式是LINQ的一部分。但是,LINQ包含了很多C#功能,包括查询语法,lambdas,泛型委托和表达式。

LINQ查询使用表达式来提供与IQueryable.相关的一些行为。例如,C#代码(表达式)被重写并作为SQL执行。您可以从How to: Use Expression Trees to Build Dynamic QueriesWalkthrough: Creating an IQueryable LINQ Provider开始,但这相当容易。


动态代码/语言实现的表达

我理解Expression API最终足够强大,可以代表大多数语言结构,并作为实现动态/解释语言的基础;虽然我从来没有以这种身份使用它。您可以在与Dynamic Language Runtime相关的材料中找到有关此用途的更多信息。