如何使用LINQ对比Department与Student列表并修改Student的IsActive属性
问题分析
原有代码存在以下几个核心问题:
- 查找效率极低:使用
departments.Any匹配DepId的逻辑时间复杂度为O(学生数量*部门数量),面对15万条学生数据时性能损耗非常大 - 重复遍历开销:
results是延迟执行的IEnumerable类型,每次调用ToList()、Exists()都会重新执行一次筛选逻辑,相当于多次重复遍历全量数据,完全无意义 - 属性名错误:Student类定义的可修改属性为
IsActive,原有代码误写为IsEnabled,赋值操作无效 - 跨线程操作违规:
GridViewStudent是UI控件,直接在Task.Run的后台线程中操作会触发跨线程访问异常
优化后实现代码
private async Task UpdateMyGrid() { departments = ....; // 部门列表赋值 students = ..... ; // 学生列表赋值 // 提前把所有部门ID转为HashSet,后续查找复杂度为O(1) var departmentIdSet = departments.Select(d => d.DepId).ToHashSet(); // 后台线程仅处理数据计算,不操作UI await Task.Run(() => { // 如果需要单独保存匹配成功的学生集合,可以打开下面这行注释 // var matchedStudents = students.Where(s => departmentIdSet.Contains(s.DepId)).ToList(); foreach (var student in students) { if (departmentIdSet.Contains(student.DepId)) { student.IsActive = false; } } }); // UI操作放到await之后,执行上下文已切回主线程,不会触发跨线程异常 GridViewStudent.ItemsSource = null; GridViewStudent.ItemsSource = students; }
优化说明
- 采用HashSet存储部门ID后,整体时间复杂度降到
O(部门数量+学生数量),15万条数据处理可以在毫秒级完成 - 仅需要遍历一次学生列表就完成所有属性修改,去掉了所有冗余遍历逻辑
- 修正了属性名错误,与类定义的
IsActive匹配,符合需求 - 拆分了数据计算和UI更新逻辑,避免了跨线程操作问题
- 如果需要保留匹配成功的学生集合单独使用,直接打开代码中
matchedStudents相关的注释即可,不影响属性修改逻辑
内容的提问来源于stack exchange,提问作者csharp_devloper31
相关产品推荐
相关产品推荐

