受到另一个关于缺失Zip函数的问题的启发:
为什么在IEnumerable接口上没有ForEach扩展方法?或在任何地方吗?唯一获得ForEach方法的类是List<>。有什么原因吗,也许是性能?
受到另一个关于缺失Zip函数的问题的启发:
为什么在IEnumerable接口上没有ForEach扩展方法?或在任何地方吗?唯一获得ForEach方法的类是List<>。有什么原因吗,也许是性能?
当前回答
部分原因是语言设计者从哲学角度不同意这一观点。
没有(和测试……)一个功能比有一个功能更省事。 它并不是真的更短(有一些传递函数的情况下,它是,但这不是主要用途)。 它的目的是产生副作用,这不是linq的目的。 为什么要用另一种方式来做我们已经拥有的功能呢?(为每一个关键字)
https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/
其他回答
还没有人指出ForEach<T>导致编译时类型检查,其中ForEach关键字是运行时检查的。
在代码中使用了这两个方法之后,我做了一些重构,我倾向于. foreach,因为我必须查找测试失败/运行时失败来找到foreach问题。
@Coincoin
foreach扩展方法的真正功能包括Action<>的可重用性,而无需向代码添加不必要的方法。假设您有10个列表,并且您希望对它们执行相同的逻辑,而对应的函数不适合您的类并且不能重用。您可以将所有逻辑保存在一个地方,而不是使用十个for循环,或者使用一个显然不属于helper的通用函数(Action<>。所以,很多行被替换成
Action<blah,blah> f = { foo };
List1.ForEach(p => f(p))
List2.ForEach(p => f(p))
等等……
逻辑是在一个地方,你没有污染你的课。
我自己也一直在想,这就是为什么我总是带着这个:
public static void ForEach<T>(this IEnumerable<T> col, Action<T> action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
foreach (var item in col)
{
action(item);
}
}
不错的扩展方法。
在3.5中,所有添加到IEnumerable中的扩展方法都是为了支持LINQ(注意它们是在System.Linq.Enumerable类中定义的)。在这篇文章中,我解释了为什么foreach不属于LINQ: 现有的LINQ扩展方法类似于Parallel.For?
因此,有很多关于ForEach扩展方法不合适的评论,因为它不像LINQ扩展方法那样返回值。虽然这是事实陈述,但并不完全正确。
LINQ扩展方法都返回一个值,所以它们可以链接在一起:
collection.Where(i => i.Name = "hello").Select(i => i.FullName);
然而,仅仅因为LINQ是使用扩展方法实现的,并不意味着扩展方法必须以相同的方式使用并返回一个值。编写一个扩展方法来公开不返回值的常见功能是完全有效的使用。
关于ForEach的具体参数是,基于扩展方法的约束(即扩展方法永远不会覆盖具有相同签名的继承方法),可能存在这样一种情况,即自定义扩展方法在所有impelement IEnumerable<T> (List<T>除外)的类上可用。这可能会导致混淆,因为根据调用的是扩展方法还是继承方法,方法开始表现不同。