LINQ更新列表内部字段:即时窗口生效,直接执行代码无效果
问题分析与解决方案
这问题我太熟了——核心原因就是LINQ的延迟执行特性在搞鬼!
你看这段代码:
item.AppUserSecurityGroupXrefs.Where(a => list.Contains(a.SecurityGroupId)) .Select(b => b.SecurityGroup) .Select(c => c.Selected = true);
这里的Select是LINQ的延迟查询操作符,它并不会立刻执行里面的赋值逻辑,只是在内存中创建了一个"待执行"的查询计划而已。只有当你枚举这个查询结果的时候(比如调用ToList()、FirstOrDefault()、foreach遍历它),里面的代码才会真正跑起来。
那为什么即时窗口里执行这行代码就生效?因为即时窗口在执行表达式时,会自动枚举查询结果来展示,相当于隐式触发了查询的执行,赋值操作也就真的跑了。而你在代码里写的这行,只是定义了查询,没有去触发它,所以Selected字段根本没被修改。
怎么解决?
有几种简单的修复方式,选哪种看你习惯:
用
ToList()触发查询执行
在最后加个ToList(),强制枚举查询结果,这样赋值就会生效:item.AppUserSecurityGroupXrefs.Where(a => list.Contains(a.SecurityGroupId)) .Select(b => b.SecurityGroup) .Select(c => c.Selected = true) .ToList(); // 加这一行,触发执行改用
foreach遍历赋值(更直观)
既然是要修改对象的属性,直接用foreach遍历比LINQ的Select更清晰,也不会有延迟执行的坑:var targetSecurityGroups = item.AppUserSecurityGroupXrefs .Where(a => list.Contains(a.SecurityGroupId)) .Select(b => b.SecurityGroup); foreach (var group in targetSecurityGroups) { group.Selected = true; }用LINQ的
ForEach方法(仅限List)
如果你的集合是List<T>类型,也可以用ForEach方法直接操作:item.AppUserSecurityGroupXrefs.Where(a => list.Contains(a.SecurityGroupId)) .Select(b => b.SecurityGroup) .ToList() .ForEach(c => c.Selected = true);
你看后面那句FirstOrDefault()能拿到值,就是因为它触发了查询枚举,所以那时候赋值已经执行了,但前面单独的Select语句没触发执行的话,大部分对象的属性还是没被修改。
内容的提问来源于stack exchange,提问作者Sandeep Thomas
相关产品推荐
相关产品推荐

