C# Expression是什么 - LINQ to SQL的基石

来源:这里教程网 时间:2026-02-21 17:34:30 作者:

Expression> 是一个表示“可被编译、也可被解析为表达式树”的委托类型,它是 LINQ to SQL(以及 EF 等查询提供程序)实现“延迟翻译成 SQL”的核心机制,不是普通方法调用的封装。

它和普通 Func 的本质区别

普通 Func 是一段可执行的 IL 代码,运行时直接调用;而 Expression> 是一段**可被遍历、分析、转换的数据结构(表达式树)**,编译器会把它生成为

Expression.Constant
Expression.Call
Expression.Lambda
等节点对象,而非机器码。

Func<int> f = () => DateTime.Now.Year + 1;</int>
→ 运行时立刻算出一个整数
Expression<func>> e = () => DateTime.Now.Year + 1;</func>
→ 得到一棵树:根是 Lambda,子节点是 Call(Now)、MemberAccess(Year)、Constant(1)、Add……

为什么 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<func>></func>
当作委托直接调用会失败——它不是可执行体。必须先调用
.Compile()
才能转成真正的
Func<t></t>

Expression<func>> expr = () => 42;</func>
int result = expr.Compile()(); // ✅ 先编译再调用
int result = expr(); // ❌ 编译不过:Expression 不支持直接调用

简单看一眼表达式树长什么样

这段代码:

Expression> e = () => "Hello".Length.ToString();

实际构建出的树大致包含:
Lambda 节点 → Call 节点(ToString)→ MemberAccess 节点(Length)→ Constant 节点("Hello")
正是这种结构,让框架能“读懂”你的意图,而不是只看到一个黑盒函数。

基本上就这些。理解 Expression 不是为了手写树,而是明白为什么 .Where(x => x.Id == id) 能变 SQL,而 .Where(x => MyHelper.IsValid(x)) 却不行——后者是 Func,没法被翻译。

相关推荐