Expression 是可解析为表达式树的数据结构,用于 LINQ to SQL 等框架将查询翻译为 SQL;而 Func 是直接执行的 IL 代码,无法被分析转换。

Expression
它和普通 Func 的本质区别
普通 FuncExpression.Constant、Expression.Call、Expression.Lambda 等节点对象,而非机器码。
- 写
Func→ 运行时立刻算出一个整数f = () => DateTime.Now.Year + 1; - 写
Expression→ 得到一棵树:根是 Lambda,子节点是 Call(Now)、MemberAccess(Year)、Constant(1)、Add……> e = () => DateTime.Now.Year + 1;
为什么 LINQ to SQL 靠它工作
LINQ 查询(如 db.Users.Where(u => u.Age > 18 && u.City == "Beijing"))中的 u => ... 必须是 Expression
- 递归遍历表达式树,识别出字段名(
Age、City)、操作符(>、==)、常量值(18、"Beijing") - 把它们映射成对应数据库的语法,生成类似
WHERE [Age] > 18 AND [City] = 'Beijing'的 SQL - 跳过不支持的操作(比如
u.Name.ToUpper()若数据库无对应函数,就可能报错或客户端求值)
你不能随便混用 Expression 和 Func
把 Expression 当作委托直接调用会失败——它不是可执行体。必须先调用 .Compile() 才能转成真正的 Func:
Expression> expr = () => 42; int result = expr.Compile()(); // ✅ 先编译再调用int result = expr(); // ❌ 编译不过:Expression 不支持直接调用
简单看一眼表达式树长什么样
这段代码:
Expression实际构建出的树大致包含:
Lambda 节点 → Call 节点(ToString)→ MemberAccess 节点(Length)→ Constant 节点("Hello")
正是这种结构,让框架能“读懂”你的意图,而不是只看到一个黑盒函数。
基本上就这些。理解 Expression 不是为了手写树,而是明白为什么 .Where(x => x.Id == id) 能变 SQL,而 .Where(x => MyHelper.IsValid(x)) 却不行——后者是 Func,没法被翻译。









