为什么ForEach Linq扩展列表而不是IEnumerable

时间:2011-04-18 15:10:21

标签: c# .net linq ienumerable linq-to-objects

  

可能重复:
  Why is there not a ForEach extension method on the IEnumerable interface?

你好,

我的问题是为什么Foreach扩展方法是在List而不是IEnumreable上定义的。我读过Eric Lippert的article,但问题是,如果有这样的方法,那么为什么它不适用于List?

4 个答案:

答案 0 :(得分:12)

List<T>.ForEach()不是扩展方法。这只是List<T>上的一种方法。

LINQ中不可用的一个主要原因(即Enumerable)是LINQ查询应该没有副作用(因此你可以,例如,多次执行查询并且在不改变它们的情况下获得相同的结果),这使得它们非常可组合。接受委托的所有LINQ操作都是Func;他们都不接受Action代表。

答案 1 :(得分:6)

这是我在Microsoft Connect网站上发布的一个错误,微软已经在即将发布的.NET版中修复了它,如下面的链接所示。

List.ForEach allows enumeration over modified version of List

这可能与答案没有直接关系,但它对我刚刚发现的内容非常有趣。

ForEach,删除(工作)

List<int> list = new List<int>(){ 1, 2, 3, 4, 5, 6};

list.ForEach(x => {
    Console.WriteLine(x);
    list.Remove(x);
});

foreach,删除(崩溃)

// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Remove(x);
}

ForEach,插入(...)

// goes in infinite loop...
list.ForEach(x => {
    list.Add(1);
});

foreach,insert(crashes)

// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Add(x);
}

所以在这里谈论可变性或不同的混淆层等的任何人,我认为它是Visual Team的完全一半实现的功能,因为如果修改了集合,枚举将总是导致问题。

尽管存在争论,我仍然认为ForEach不应该允许修改,它纯粹用于枚举,它的foreach(x中的var项)语法或x.ForEach(x =&gt; {没有区别})语法。

我不同意Eric,我只是简单地看到BCL团队已经在IEnumerable和list.ForEach上实现了这个功能。

“为什么”是完全主观的,例如,Silverlight添加了复杂的散列算法,并且MD5落后于其他地方我们广泛使用MD5的其他地方。更多的是需要多少东西以及选择是否将其包含在框架中的人。

在IEnumerable中没有ForEach没有任何逻辑或哲学原因。有很多这样的缺点我认为.NET会随着时间的推移而改进。

答案 2 :(得分:1)

应该避免使用LINQ变异状态并且不鼓励,LINQ的重点是查询和转换数据,但没有到位突变 - 你失去了LINQ功能方法的许多好处(即没有副作用) ,如果你改变了状态,那么相同的输入产生相同的输出。

Linq在正常ForEach()循环上提供foreach扩展方法没有任何好处,除了它可以帮助你改变状态 - 因此它没有实现(至少我对它的看法) ,带上一粒盐。)

答案 3 :(得分:0)

'为什么'超出了我的范围;我没有制作C#。但是,它是有道理的,因为它将完全枚举您的集合,而大多数LINQ运算符被懒惰地评估。