Expression<Func<T>> vs Func<T>:C# 优化秘诀

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Expression\n\n

想象一下:你正在编写 C# 代码。需要将一个过滤条件传递给一个方法。该选择什么:Func<User, bool> 还是 Expression<Func<User, bool>>?看起来差别很小——两者都接收一个用户并返回一个 bool。但在幕后,却隐藏着一个充满差异的宇宙。

\n\n

在 Stack Overflow 上,这个问题获得了数千次浏览——这并非没有原因。今天我们将弄清楚为什么 Expression<Func<T>> 可能比普通的 Func<T> 更强大、更快速、更安全。最重要的是——何时使用它们,以免搬起石头砸自己的脚。

\n\n

快速入门:什么是 Func 和 Expression?

\n\n

Func<T> 只是一个委托。一个准备好执行的函数,编译后的机器码。你向它传递数据——它处理这些数据。快速、高效,但……不透明。

\n\n
Func<User, bool> isAdult = user => user.Age >= 18;\nbool result = isAdult(someUser); // 立即执行
\n\n

Expression<Func<T>> 是一个表达式树。不是代码,而是代码的描述。你不能直接调用它——要么需要将其编译成委托(通过 .Compile()),要么需要分析其结构。

\n\n
Expression<Func<User, bool>> expr = user => user.Age >= 18;\n// 不能直接调用:expr(someUser) —— 编译错误\nvar compiled = expr.Compile();\nbool result = compiled(someUser); // 现在可以了
\n\n

看起来,何必多此一举?但正是这种“描述性”打开了通往魔法的大门。

\n\n

场景 1:LINQ to Objects(内存中操作)

\n\n

当你处理内存中的集合时(例如 List<T>),LINQ to Objects 使用 Func<T>。这里不需要表达式树——所有操作都在同一进程中执行。

\n\n
var users = new List<User>();\nvar adults = users.Where(u => u.Age >= 18).ToList(); // Func<User, bool>
\n\n

性能极佳:没有解析表达式树的开销。如果你只处理本地数据——放心使用 Func。它更快、更简单。

\n\n

场景 2:LINQ to SQL / Entity Framework(数据库操作)

\n\n

而这里,魔法开始了。当你编写:

\n\n
var adults = dbContext.Users.Where(u => u.Age >= 18).ToList();
\n\n

Entity Framework 不会执行你的 C# 代码。相反,它会分析传递的 表达式树 并将其转换为 SQL 查询:

\n\n
SELECT * FROM Users WHERE Age >= 18
\n\n

如果你传递了 Func,EF 将无法“窥视内部”——它只会从表中加载 所有 用户并在内存中执行过滤。想象一下:一张包含 1000 万条记录的表——所有这些记录都通过网络传输到你的应用程序,以便在客户端进行过滤。

\n\n

Expression<Func<T>> 允许 EF(或任何其他 IQueryable 提供程序)读取你的条件,将其翻译成数据库语言(SQL、MongoDB 查询、OData 等)并在服务器端执行过滤。

\n\n

性能:基准测试与实际数据

\n\n

让我们看看具体数字。举一个简单的例子:按年龄过滤 100,000 个用户。

\n\n
// 选项 1:Func —— 加载所有用户,在内存中过滤\nvar allUsers = dbContext.Users.ToList(); // SELECT * FROM Users\nvar adults1 = allUsers.Where(u => u.Age >= 18).ToList();\n\n// 选项 2:Expression —— 在服务器端过滤\nvar adults2 = dbContext.Users.Where(u => u.Age >= 18).ToList(); // SELECT * FROM Users WHERE Age >= 18
\n\n

结果(近似值,但具有代表性):

\n
    \n

博客

书籍推荐