什么是表达式树
了解如何将代码表示为数据结构。
什么是表达式树 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
代码即数据
表达式树会将代码表示为一种可以在运行时检查的数据结构,而不是只能运行的已编译指令。C# 使用Expression<TDelegate>实现这一点。
Lambda 到委托与表达式树
将 Lambda 赋给Func<...>后,您会得到可运行的代码。将同一个 Lambda 赋给Expression<Func<...>>后,编译器会构建一棵描述该 Lambda 的树。
using System;
using System.Linq.Expressions;
Func<int, int> runnable = x => x + 1; // compiled delegate
Expression<Func<int, int>> tree = x => x + 1; // data structure
Console.WriteLine(runnable(5)); // 6
Console.WriteLine(tree); // x => (x + 1)检查表达式树
由于表达式树是数据,您可以读取其中的各个部分:参数、body 和节点类型。
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x + 1;
Console.WriteLine(tree.Parameters[0].Name); // x
Console.WriteLine(tree.Body.NodeType); // Add
Console.WriteLine(tree.ReturnType); // System.Int32表达式层次结构
每个节点都派生自System.Linq.Expressions.Expression。常见类型包括BinaryExpression、ParameterExpression、ConstantExpression和MethodCallExpression。
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x + 1;
var body = (BinaryExpression)tree.Body;
Console.WriteLine(body.Left); // x
Console.WriteLine(body.Right); // 1仅允许单表达式 Lambda
您只能将单表达式 Lambda 转换为表达式树。带语句体的 Lambda(包含花括号)不能转换为表达式树。
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> ok = x => x * 2; // fine
// Expression<Func<int,int>> bad = x => { return x*2; }; // compile error
Console.WriteLine(ok); // x => (x * 2)为什么这很重要
表达式树让库能够理解您的代码,而不只是运行它。LINQ 提供程序可以将表达式树转换为 SQL、动态查询或其他目标语言。
NodeType 告诉您操作类型
NodeType属性是一个ExpressionType枚举值,用于标识该节点执行的操作。
using System;
using System.Linq.Expressions;
Expression<Func<int, bool>> tree = x => x > 10;
Console.WriteLine(tree.Body.NodeType); // GreaterThan常量与参数
ParameterExpression代表一个 input;ConstantExpression则保存嵌入代码中的字面值。
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x + 5;
var body = (BinaryExpression)tree.Body;
Console.WriteLine(body.Left.GetType().Name); // ParameterExpression (or TypedParameterExpression)
Console.WriteLine(((ConstantExpression)body.Right).Value); // 5表达式树中的方法调用
调用方法的 Lambda 会变成MethodCallExpression,并公开该方法及其参数。
using System;
using System.Linq.Expressions;
Expression<Func<string, int>> tree = s => s.Length;
// member access here; a call example:
Expression<Func<string, string>> call = s => s.ToUpper();
var mc = (MethodCallExpression)call.Body;
Console.WriteLine(mc.Method.Name); // ToUpper表达式树是不可变的
表达式树是不可变的。要“更改”表达式树,您需要根据其各个部分构建一棵新树,这正是访问器和重写器的工作方式。
综合运用
这里将端到端分析一棵小型谓词树:参数、运算符和常量。
using System;
using System.Linq.Expressions;
Expression<Func<int, bool>> isAdult = age => age >= 18;
var body = (BinaryExpression)isAdult.Body;
Console.WriteLine(isAdult.Parameters[0].Name); // age
Console.WriteLine(body.NodeType); // GreaterThanOrEqual
Console.WriteLine(((ConstantExpression)body.Right).Value); // 18快速检查
请确认表达式树的特殊之处。
回顾
您已经学习了表达式树的含义。
Expression<TDelegate>将代码表示为可检查的数据。- 节点包括参数、常量、二元运算和方法调用。
- 只有单表达式 Lambda 才符合要求。
- 表达式树是不可变的;重写会构建新树。
常见问题解答
「什么是表达式树」课时是免费的吗?
是的 — 「什么是表达式树」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「什么是表达式树」这节课中我会学到什么?
了解如何将代码表示为数据结构。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「什么是表达式树」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。