【发布时间】:2010-11-10 15:19:30
【问题描述】:
我想很好地掌握这个主题,因此想向社区提出以下问题:
- 表达式树有什么好处?
- 这句话到底是什么意思:“表达式树是编译为代码的数据”?
- .net 上下文中的表达式树和函数式编程解决了哪些常见挑战?
- 有什么好的在线资源可以加快主题速度?
【问题讨论】:
标签: .net functional-programming expression expression-trees
我想很好地掌握这个主题,因此想向社区提出以下问题:
【问题讨论】:
标签: .net functional-programming expression expression-trees
表达式树有什么好处?
表达式树允许程序在运行时以简化的方式操作它自己的部分实现。它们允许将表达式作为其结构的表示来传递,而不仅仅是可以调用的委托。
这句话到底是什么意思:“表达式树是编译为代码的数据”?
C#/.NET 之前的语言已经支持这种操作……最好的例子是 LISP。在程序内的数据结构中表示程序结构的能力称为homoiconicity。 C# 以表达式树的形式支持有限的同音性。 C# 语言允许从代码中的(子集)表达式透明地创建表达式树。例如:
int x = 3;
Expression<Func<bool>> IsXLessThan4Expr = () => x < 4;
Func<bool> IsXLessThan4 = () => x < 4;
变量IsXLessThan4Expr 是从 lambda 表达式中捕获的表达式树。如果我们想了解它的结构是什么,我们现在可以遍历该表达式的表示 - 如果我们愿意,可以操纵它。相比之下,委托IsXLessThan4 不能被检查……它只能被调用。当然,您可以始终获取任何方法的原始 IL(假设您拥有必要的权限)——但是从 IL 反转程序的逻辑结构比从表达式树反转要困难得多。
.net 环境中的表达式树和函数式编程解决了哪些常见挑战?
使用表达式树解决重要问题的最佳示例是在 LINQ-to-SQL 中,其中IQueryable 的实现能够将用 C# 编写的查询表达式树转换为等效的 SQL 查询,可以由数据库执行。
表达式树还可以动态生成 C# 代码 - 因为表达式树可以编译为 lambda。这是一个例子:
var paramNotification =
Expression.Parameter(typeof (NotificationEntry), "noti");
Func<NotificationEntry, bool> predicate =
m_PredicateExpr = Expression.Lambda<Func<NotificationEntry, bool>>(
Expression.LessThan(
Expression.Property(paramNotification, "Value"),
Expression.Constant(100)),
new[] {paramNotification})
.Compile();
上面的 sn-p 创建了一个表达式,将 NotificationEntry 对象的 Value 字段与一些提供的常量 (100) 进行比较 - 并将其编译成我们可以调用的 lambda。
有什么好的在线资源可以加快这个主题的速度?
MSDN 可能是您目前最好的选择。
【讨论】:
Compile() 将表达式树转换为代码 - 这将返回适当的委托。
IQueryable 实现使用检查和转换表达式树的能力来允许 C# 代码表示对其他类型资源的查询。他们通过访问表达式的表示并将其转换为适合其领域的形式来做到这一点。真正好的是,在 C# 中,一个 lambda 可以透明地传递给任何接受 Expression<...> 类型参数的方法 - 这允许以自然的方式编写消费代码,而不必担心转换的底层细节。
它们带来了获取源代码并在执行时“理解”它的能力 - LINQ 提供程序是主要目标
嗯,表达式树通常是从源代码构建的(例如,转换后的 lambda 表达式),但不是将源代码编译成 可执行文件 形式,而是构建成其他代码可以执行的树检查。 (更准确地说,编译器获取源代码,并发出可执行代码,然后在执行时构建表达式树。)
说实话,表达式树和函数式编程对我来说似乎有些正交。两者都经常处理高阶函数,但仅此而已。
【讨论】:
IQueryable,您将看到表示查询的表达式树 - 然后您需要检查这些表达式树并将它们转换为适当的格式。跨度>