DefaultIfEmpty() 解决的是集合为空时聚合报错的场景,但需注意区分”集合为空”和”元素字段为 null”两种情况。
// 集合可能为空,DefaultIfEmpty 让 Sum 有默认值 0
money = s.Where(w => w.zt == (int)Print)
.DefaultIfEmpty()
.Sum(w => w.je);Code language: JavaScript (javascript)
static void Main(string[] args)
{
using (var dbContext = new DataClasses1DataContext())
{
var q = from u in dbContext.User
orderby u.Name descending, u.Password ascending
where u.ID > 100
select u;
var list = q.ToList(); // 如果无记录,下面直接 Sum(m=>m.ID) 会抛异常
// 用 DefaultIfEmpty + 判空解决
var total = q.DefaultIfEmpty().Sum(m => m == null ? 0 : m.ID);
}
}Code language: JavaScript (javascript)
两种 null 场景对比:
| 场景 | 说明 | 解决方式 |
|---|---|---|
| 集合为空(无记录) | Sum() 直接抛异常 | DefaultIfEmpty() 返回含一个 null 元素的序列 |
| 元素字段为 null | 如 w.je 为 null(可空类型) | Sum(w => w.je ?? 0) |
对应写法:
// 场景1:集合可能为空
var total1 = q.DefaultIfEmpty().Sum(m => m == null ? 0 : m.ID);
// 场景2:字段可能为 null(je 是 decimal?)
var total2 = s.Sum(w => w.je ?? 0);
// 两种同时处理
var total3 = s.Where(w => w.zt == 1)
.DefaultIfEmpty()
.Sum(w => w?.je ?? 0);Code language: JavaScript (javascript)
关键要点:
| 要点 | 说明 |
|---|---|
DefaultIfEmpty() | 空集合返回含一个 null 的单元素序列,让聚合不抛异常 |
Sum 直接对空 IQueryable 调用 | 会抛异常,必须先 DefaultIfEmpty() |
| 字段为 null | 用 ?? 0 或 w==null?0:w.Field 处理 |
| 元素空 vs 字段空 | 元素空靠 DefaultIfEmpty(),字段空靠 ?? 或判空 |
DefaultIfEmpty 位置 | 在聚合方法之前调用,不能写在 Where 后面忘了接聚合 |
Previous: 多字段排序(orderby)
Next: GroupBy 后转为 Dictionary