Expression类的目的是什么?

Ste*_*fen 55 c# lambda expression-trees

我想知道在内部包装代表之间究竟有什么区别Expression<>

我看到Expression<Foo>LinQ使用了很多,但到目前为止,我还没有找到任何解释它之间差异的文章,只是使用了一个委托.

例如

Func<int, bool> Is42 = (value) => value == 42;
Run Code Online (Sandbox Code Playgroud)

Expression<Func<int, bool>> Is42 = (value) => value == 42;
Run Code Online (Sandbox Code Playgroud)

Jef*_*ado 63

通过将lambda存储为委托,您将存储执行某些操作的委托的特定实例.它无法修改,你只需要调用它.一旦你有了你的代表,你在检查它的功能和诸如此类的东西方面的​​选择有限.

通过将lambda存储为表达式,您将存储表示委托的表达式树.它可以被操纵来做其他事情,比如改变它的参数,改变身体并让它做一些截然不同的事情.它甚至可以编译回代表,所以如果你愿意,你可以打电话给代表.您可以轻松地检查表达式,以查看其参数是什么,它做了什么以及如何做.这是查询提供程序可以用来理解表达式并将其转换为另一种语言(例如为相应的表达式树编写SQL查询).

使用表达式动态创建委托比发出代码要容易得多.您可以将更高级别的代码视为与编译器查看代码而非低级别并将代码视为IL指令非常相似的表达式.

因此,使用表达式,您可以比简单的匿名委托做更多的事情.虽然它不是真正免费的,但如果你运行编译表达式与常规方法或匿名委托相比,性能将受到影响.但这可能不是问题,因为使用表达式的其他好处对您来说可能很重要.


Tim*_*ers 16

Func<>只是一种代表类型.表达式是完整操作树的运行时表示,可选地,可以在运行时将其编译成委托.这个树由Linq-to-SQL之类的Expression解析器解析,以生成SQL语句或执行其他聪明的操作.将lambda指定给Expression类型时,编译器会生成此表达式树以及常用的IL代码.更多关于表达树.


Uco*_*dia 12

为了说明其他答案,如果您编译这两个表达式并查看编译器生成的代码,那么您将看到:

Func<int, bool> Is42 = (value) => value == 42;

Func<int, bool> Is42 = new Func<int, bool>((@value) => value == 42);
Run Code Online (Sandbox Code Playgroud)


Expression<Func<int, bool>> Is42 = (value) => value == 42;

ParameterExpression[] parameterExpressionArray;
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "value");
Expression<Func<int, bool>> Is42 = Expression.Lambda<Func<int, bool>>(Expression.Equal(parameterExpression, Expression.Constant(42, typeof(int))), new ParameterExpression[] { parameterExpression });
Run Code Online (Sandbox Code Playgroud)

  • 他在问这些差异是什么,生成的代码是不言自明的. (6认同)

Nic*_*ler 5

表达式树允许您在代码中检查表达式中的代码。

例如,如果您传递了这个表达式: o => o.Name,您的代码可以发现Name正在表达式内部访问该属性。