为什么ForEach Linq扩展出现在List上而不是IEnumerable上

本文关键字:IEnumerable List Linq ForEach 扩展 为什么 | 更新日期: 2023-09-27 17:50:23

可能重复:
为什么IEnumerable接口上没有ForEach扩展方法?

你好,

我的问题是为什么Foreach扩展方法是在List上定义的,而不是在IEnumreable上定义的。我读过埃里克·利珀特的文章,但问题是,如果有这样的方法太糟糕了,为什么会出现在《名单》上?

为什么ForEach Linq扩展出现在List上而不是IEnumerable上

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

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

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

List.ForEach允许对List的修改版本进行枚举

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

对于每个,删除(工作(

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);
}

对于每个,插入(…(

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

foreach,插入(崩溃(

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

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

尽管有这些争论,我仍然认为ForEach应该允许修改,它纯粹用于枚举,无论是ForEach(x中的var项(语法还是x.ForEach(x=>{}(语法都没有区别。

我不同意Eric的观点,我只是认为BCL团队已经在IEnumerable和list上实现了这个功能。ForEach有故障。

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

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

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

与普通的foreach循环相比,Linq提供ForEach()扩展方法没有任何好处,只是它可以帮助你改变状态——因此它没有实现(这至少是我的看法,对此持保留态度(。

"为什么"不在我的范围内;我没做C#。然而,这是有意义的,因为它将完全枚举您的集合,而大多数LINQ运算符都是延迟求值的。

相关文章: