LINQ查询Where后无法使用ForEach()问题及LINQ替代方案咨询
嘿,我来帮你拆解这个问题:
首先,你为啥在Where()之后没法直接用ForEach()?核心原因是:Where()返回的是IEnumerable<T>接口类型,而ForEach()是List<T>类特有的方法,并不是IEnumerable<T>的标准扩展方法,所以编译器找不到这个方法,自然报错。另外提一句,你代码里的b.EpayInfo.result=="result"应该是笔误吧?看起来你是想给属性赋值,应该写成b.EpayInfo.result = "result"才对😉
下面给你几个符合LINQ风格的解决方案,你可以根据需求选:
方案1:先转List再执行修改(最直接)
既然List<T>自带ForEach(),我们可以在筛选后先把结果转成List,再执行修改操作,同时把这个List作为最终的newResult:
// 先筛选,转成List,再批量修改属性,最后保留这个List var newResult = result .Where(a => a.EpayInfo.condition == "condition") .ToList(); newResult.ForEach(b => b.EpayInfo.result = "result");
这里要注意:因为EpayInfo是EF实体(引用类型),修改它的属性会直接影响原对象的状态,如果你不需要保留原始数据的话,这个方案简单又高效。
方案2:用Select创建新对象(无副作用的函数式写法)
如果你想遵循LINQ的函数式设计理念(不修改原对象,只返回新结果),可以用Select()创建包含修改后实体的新匿名类型集合:
var newResult = result .Where(a => a.EpayInfo.condition == "condition") .Select(a => new { a.ePayDetailID, a.WATStatus, // 复制原EpayInfo的属性并修改result,这里需要手动复制所有必要属性 EpayInfo = new ePayReconDetail { ePayReconDetailID = a.EpayInfo.ePayReconDetailID, condition = a.EpayInfo.condition, result = "result", // 记得把其他需要保留的属性也复制过来... }, a.WATinfo }) .ToList();
这种方式不会修改原有的EF实体对象,适合需要保留原始数据的场景,缺点是需要手动复制实体的所有属性,稍微麻烦一点。
方案3:自定义IEnumerable的ForEach扩展方法(一劳永逸)
如果你经常需要在IEnumerable<T>上直接用ForEach(),可以自己写一个扩展方法,以后就能链式调用了:
public static class EnumerableExtensions { public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action) { foreach (var item in source) { action(item); yield return item; } } }
定义好之后,你就可以像最开始想的那样链式调用了,还能直接返回处理后的集合:
var newResult = result .Where(a => a.EpayInfo.condition == "condition") .ForEach(b => b.EpayInfo.result = "result") .ToList();
这个扩展方法会遍历每个元素执行修改操作,同时返回原元素(因为是引用类型,修改已经生效),最后转成List得到newResult。
最后说一句
其实LINQ的设计初衷是用于查询数据,修改数据的操作用普通foreach循环本身也非常清晰,你已经实现了这种方式,完全没问题。上面的方案只是给你提供LINQ风格的替代选项,按需选用就好~
内容的提问来源于stack exchange,提问作者YHTAN

