受到另一个关于缺失Zip函数的问题的启发:

为什么在IEnumerable接口上没有ForEach扩展方法?或在任何地方吗?唯一获得ForEach方法的类是List<>。有什么原因吗,也许是性能?


当前回答

请注意,MoreLINQ NuGet提供了您正在寻找的ForEach扩展方法(以及执行委托并产生结果的Pipe方法)。看到的:

https://www.nuget.org/packages/morelinq https://code.google.com/p/morelinq/wiki/OperatorsOverview

其他回答

我的版本是一个扩展方法,允许你在T的IEnumerable上使用ForEach

public static class EnumerableExtension
{
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        source.All(x =>
        {
            action.Invoke(x);
            return true;
        });
    }
}

当你想要返回一些东西时,你可以使用select。 如果不需要,可以先使用ToList,因为您可能不想修改集合中的任何内容。

虽然我同意在大多数情况下使用内置的foreach构造更好,但我发现在foreach <>扩展上使用这种变体比自己在常规foreach中管理索引要好一些:

public static int ForEach<T>(this IEnumerable<T> list, Action<int, T> action)
{
    if (action == null) throw new ArgumentNullException("action");

    var index = 0;

    foreach (var elem in list)
        action(index++, elem);

    return index;
}
Example
var people = new[] { "Moe", "Curly", "Larry" };
people.ForEach((i, p) => Console.WriteLine("Person #{0} is {1}", i, p));

会给你:

Person #0 is Moe
Person #1 is Curly
Person #2 is Larry

一种解决方法是编写. tolist()。ForEach(x =>…)

pros

易于理解——读者只需要知道c#附带了什么,而不需要知道任何额外的扩展方法。

语法干扰非常温和(只添加了一点无关的代码)。

通常不需要额外的内存,因为本机. foreach()必须实现整个集合。

cons

操作顺序并不理想。我宁愿实现一个元素,然后付诸行动,然后重复。这段代码首先实现所有元素,然后依次对它们进行操作。

如果意识到列表抛出异常,则永远无法对单个元素进行操作。

如果枚举数是无限的(就像自然数一样),那么你就不走运了。

我想对Aku的回答进行进一步阐述。

如果你想调用一个方法的唯一目的是它的副作用,而不是首先迭代整个枚举对象,你可以使用这个:

private static IEnumerable<T> ForEach<T>(IEnumerable<T> xs, Action<T> f) {
    foreach (var x in xs) {
        f(x); yield return x;
    }
}