DefaultIfEmpty 处理空集合聚合

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 元素的序列
元素字段为 nullw.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?? 0w==null?0:w.Field 处理
元素空 vs 字段空元素空靠 DefaultIfEmpty(),字段空靠 ?? 或判空
DefaultIfEmpty 位置在聚合方法之前调用,不能写在 Where 后面忘了接聚合

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注