【发布时间】:2011-12-11 21:55:44
【问题描述】:
有没有更好的方法来使用 LINQ 完成这些任务?
IEnumerable<SideBarUnit> sulist1 = newlist.Where(c => c.StatusID == EmergencyCV.ID);
foreach (SideBarUnit su in sulist1) su.color = "Red";
【问题讨论】:
有没有更好的方法来使用 LINQ 完成这些任务?
IEnumerable<SideBarUnit> sulist1 = newlist.Where(c => c.StatusID == EmergencyCV.ID);
foreach (SideBarUnit su in sulist1) su.color = "Red";
【问题讨论】:
最简单的方法是定义一个foreach 扩展方法,允许您将其添加到此类查询的末尾。例如
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action) {
foreach (var cur in enumerable) {
action(cur);
}
}
...
用法:
newlist
.Where(c => c.StatusID == EmergencyCV.ID)
.ForEach(cur => cur.color = "Red");
【讨论】:
您可以这样做,正如此处的其他答案所指出的那样,但是您不再使用 LINQ。
Eric Lippert 写了an excellent blog post about this very subject,我强烈建议您阅读。摘录如下:
我在哲学上反对提供这种方法,原因有两个。
第一个原因是这样做违反了所有其他序列运算符所基于的函数式编程原则。显然调用此方法的唯一目的是产生副作用。
表达式的目的是计算一个值,而不是产生副作用。
...
第二个原因是这样做会给语言增加零新的表示能力。这样做可以让你重写这段非常清晰的代码:
foreach(Foo foo in foos){ statement involving foo; }进入这段代码:
foos.ForEach((Foo foo)=>{ statement involving foo; });它使用几乎完全相同的字符,但顺序略有不同。然而,第二个版本更难理解、更难调试,并且引入了闭包语义,从而可能以微妙的方式改变对象的生命周期。
【讨论】:
使用List.ForEach()方法:
IEnumerable<SideBarUnit> sulist1 =
newlist.Where(c => c.StatusID == EmergencyCV.ID)
.ToList()
.ForEach(item => item.color = "Red");
PS:我知道 Eric Lippert 的 article 关于 ForEach() vs foreach,但无论如何它很有用,我更喜欢它而不是 for/foreach 循环
编辑:关于评论中关于性能命中的问题
Enumerable.ToList() 实现为
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
所以性能下降是时候创建一个新的List<>() 实例了。
MSDN 为List<>(IEnumerable<>)ctor 说下一个:
初始化包含元素的 List 类的新实例 从指定集合复制,并且有足够的容量容纳复制的元素数量。
所以会有所有列表的复制操作
【讨论】:
ForEach 不是 Linq 独有的“功能”。事实上,它与 Linq 完全无关。所以,我假设你的答案,真的,是“不,但这里有一个替代方案。”关于 why 的建议将是这个答案的一个很好的输入 - 而不是 OP 带着这是 Linq 的错误印象。
ToLisT() 调用之后结束
Linq 是关于选择,而不是更新。 但是你可以使用 ToList 和 List 的 ForEach 来更新元素:
newlist.Where(c => c.StatusID == EmergencyCV.ID).
ToList().
ForEach(su => su.color = "Red");
我不确定可读性是否更好......
【讨论】:
您可以在 Select 语句中使用匿名方法:
var sulist1 = newlist.Where(c => c.StatusID == EmergencyCV.ID)
.Select(c => {
c.color = "Red";
return c;
});
【讨论】:
LINQ 的目的主要是查询/投影/转换数据。
您可能想要使用 ForEach 扩展方法。但请参阅this discussion 了解更多详情。
【讨论】: