关于c#:为什么ForEach Linq扩展列表而不是IEnumerable

why ForEach Linq Extension on List rather than on IEnumerable

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why is there not a ForEach extension method on the IEnumerable interface?

你好,

我的问题是为什么foreach扩展方法是在列表上定义的,而不是IEnumreable。我读过埃里克·利珀特的文章,但重点是,如果有这样的方法比为什么有列表更糟糕?


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

其中一个主要原因是它在LINQ中不可用(即,Enumerable)是LINQ查询应该没有副作用(因此,您可以多次执行一个查询并获得相同的结果而不更改它们),这使得它们非常可组合。所有接受委托的LINQ操作都是针对Func的;没有一个接受Action委托。


这是我在Microsoft Connect网站上发布的一个bug,微软已经在下面的链接中提到的即将发布的.NET版本中修复了它。

list.foreach允许对修改后的列表版本进行枚举

这可能与答案没有直接关系,但我刚刚发现的情况很有趣。

foreach,删除(Works)

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

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

foreach,删除(崩溃)

1
2
3
4
5
6
// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Remove(x);
}

foreach,插入(…)

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

foreach,insert(崩溃)

1
2
3
4
5
6
// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Add(x);
}

因此,任何在这里讨论可变性或不同的混淆层等的人,我认为它完全是可视团队实现的一半特性,因为如果修改集合,枚举总是会导致问题。

尽管有很多参数,但我仍然没有看到foreach允许修改的任何原因,它纯粹用于枚举,无论是它的foreach(x中的var item)语法还是x.foreach(x=>)语法,都没有区别。

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

"为什么"是完全主观的,例如,Silverlight添加了复杂的哈希算法,并将MD5留在了我们如此广泛使用MD5的其他地方。更多的是需要多少东西,以及谁选择是否将其包含在框架中。

在IEnumerable中没有foreach根本没有逻辑或哲学上的原因。有许多这样的缺失点,我认为.NET会随着时间的推移而改进。


归根结底,使用LINQ的突变状态应该避免,而不是鼓励,LINQ的重点是查询和转换数据,但不是就地突变-如果您确实发生了突变状态,您会失去许多LINQ功能方法的好处(即没有副作用,相同的输入产生相同的输出)。

在正常的foreach循环上,linq提供ForEach()扩展方法没有任何好处,除了它可以帮助您处于突变状态之外——因此它没有被实现(至少这是我的看法,用一粒盐)。


"为什么"超出了我的范围;我没有做C。但是,它是有意义的,因为它将完全枚举集合,而大多数LINQ运算符的计算都比较慢。