Lambda 表达式不是“方法”,而是匿名函数的简洁写法 —— 它可以赋值给委托或表达式树,但本身不构成独立方法。
什么时候必须用 Func
或 Action
接收 Lambda
当你把 Lambda 当作参数传给方法(比如
Where、
Select、
Invoke)时,编译器需要知道它的签名。此时你得用预定义委托类型:
Func<t bool></t>对应
x => x > 0(有返回值)
Action<t></t>对应
x => Console.WriteLine(x)(无返回值) 直接写
(int x) => x * 2没问题,但若想存成变量,就得声明类型:
Func<int int> doubleIt = x => x * 2;</int>
=>
左右两边不能随意省略括号和花括号
省略规则有严格限制,错一点就编译失败:
单个参数可省括号:x => x + 1✅;但多个或零参数不行:
(x, y) => x + y✅,
() => 42✅,
=> 42❌ 单条语句可省花括号和
return:
x => x.ToString()✅;但多条语句必须加:
x => { Console.WriteLine(x); return x; } ✅
返回对象字面量要包括号:() => new { Name = "A", Id = 1 } ✅;() => { Name = "A" } ❌(语法错误)
在 LINQ 查询中,Lambda 和表达式树的区别影响运行位置
这是最容易被忽略的性能与兼容性坑:
对IEnumerable<t></t>调用
.Where(x => x.Name.Contains("a")) → 在内存中执行(C# 编译为委托)
对 IQueryable<t></t>(如 EF Core 的
DbSet)调用同一条 Lambda → 被转成 SQL,
Contains变成
LIKE '%a%',但
x.Name?.Length > 0会报错(数据库不支持空条件链) 自定义方法(如
IsValid(x))无法被翻译成 SQL,EF 会抛
InvalidOperationException: The LINQ expression could not be translated
真正难的不是写法,是判断 Lambda 最终绑定到委托还是
Expression<func>></func>—— 这决定了它在哪执行、能用什么语法、出错时提示是否友好。
