LINQ分组键可为空时如何实现空值优先再降序排序并避免空引用异常
异常根因
当前排序逻辑的问题主要有两点:
- 单
OrderBy的升序逻辑无法满足需求:把空值判断和EziScheduleId取值揉在一起,默认按升序排序的规则,会让非空Schedule的记录按EziScheduleId从小到大排,完全不符合降序要求,还会把Schedule为null的组、Schedule非空但EziScheduleId为null的组混在一起。 - 多层排序下的空值防护缺失:如果后续拆分排序层、直接访问
x.Schedule.EziScheduleId,就会对Schedule为null的元素做属性访问,直接触发空引用,这也是当前异常的直接来源。
修正实现
按需求拆分为两层排序,逻辑完全适配引用类型分组键的空值场景:
- 第一层排序:利用bool类型排序时
false(0)优先于true(1)的规则,以x.Schedule != null为键做升序排列,所有Schedule为null的记录(对应键值false)会被固定到序列最前端。 - 第二层排序:在同序段内按EziScheduleId做降序排列,取排序键时做空值判断,避免空引用。
修正后代码
var v25 = (from transaction in filteredTransactions join schedule in schedules on new { siteId = transaction.LoginSiteID, startDate = transaction.LoginDateTime.Date, payrollNumber = transaction.PayrollNumber } equals new { siteId = schedule.SiteId, startDate = schedule.StartTime.Value.Date, payrollNumber = schedule.PayrollNumber } into ezi_s_t from scheduleTransactions in ezi_s_t.DefaultIfEmpty() group transaction by scheduleTransactions into groupedScheduleTransactions select new { Schedule = groupedScheduleTransactions.Key, Transactions = groupedScheduleTransactions.ToList() } ) // 所有Schedule为null的记录排到最前 .OrderBy(x => x.Schedule != null) // 非空Schedule按EziScheduleId降序,空值组返回固定值不破坏已有顺序 .ThenByDescending(x => x.Schedule == null ? null : x.Schedule.EziScheduleId) .ToList();
注意点
- 第二层排序返回的
null仅作为空值组的占位值,因为空值组已经在第一层排序中被全部前置,它们在第二层排序中的相对顺序不会被打乱,占位值不会影响最终排序结果。 - 整个逻辑没有依赖值类型可空的
HasValue判断,完全适配引用类型分组键的空值场景,不会触发空引用。
内容的提问来源于stack exchange,提问作者K.Z
相关产品推荐
相关产品推荐

