我想在LINQ中执行以下等效操作,但我无法确定如何执行:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

真正的语法是什么?


当前回答

MoreLinq有IEnumerable<T>.ForEach和许多其他有用的扩展。仅为ForEach使用依赖关系可能不值得,但其中有很多有用的东西。

https://www.nuget.org/packages/morelinq/

https://github.com/morelinq/MoreLINQ

其他回答

我采用了Fredrik的方法并修改了返回类型。

这样,该方法与其他LINQ方法一样支持延迟执行。

EDIT:如果这一点不清楚,则此方法的任何用法都必须以ToList()或任何其他方式结束,以强制该方法处理完整的可枚举对象。否则,将不会执行该操作!

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach (T item in enumeration)
    {
        action(item);
        yield return item;
    }
}

下面是帮助您了解它的测试:

[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
    IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};

    var sb = new StringBuilder();

    enumerable
        .ForEach(c => sb.Append("1"))
        .ForEach(c => sb.Append("2"))
        .ToList();

    Assert.That(sb.ToString(), Is.EqualTo("121212"));
}

如果最后删除ToList(),则会看到测试失败,因为StringBuilder包含一个空字符串。这是因为没有方法强制ForEach枚举。

ForEach也可以链接,只需在动作后放回桩线即可。保持流利


Employees.ForEach(e=>e.Act_A)
         .ForEach(e=>e.Act_B)
         .ForEach(e=>e.Act_C);

Orders  //just for demo
    .ForEach(o=> o.EmailBuyer() )
    .ForEach(o=> o.ProcessBilling() )
    .ForEach(o=> o.ProcessShipping());


//conditional
Employees
    .ForEach(e=> {  if(e.Salary<1000) e.Raise(0.10);})
    .ForEach(e=> {  if(e.Age   >70  ) e.Retire();});

实现的一个版本。

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (T item in enu) action(item);
    return enu; // make action Chainable/Fluent
}

编辑:Lazy版本使用的是收益率返回,如下所示。

public static IEnumerable<T> ForEachLazy<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (var item in enu)
    {
        action(item);
        yield return item;
    }
}

Lazy版本需要具体化,例如ToList(),否则什么都不会发生。请参阅以下ToolmakerSteve的精彩评论。

IQueryable<Product> query = Products.Where(...);
query.ForEachLazy(t => t.Price = t.Price + 1.00)
    .ToList(); //without this line, below SubmitChanges() does nothing.
SubmitChanges();

我将ForEach()和ForEachLazy()都保存在库中。

很多人都提到过,但我不得不把它写下来。这不是最清晰/最可读吗?

IEnumerable<Item> items = GetItems();
foreach (var item in items) item.DoStuff();

简短而简单(st)。

对于VB.NET,应使用:

listVariable.ForEach(Sub(i) i.Property = "Value")

IEnumerable没有ForEach扩展;仅适用于列表<T>。所以你可以

items.ToList().ForEach(i => i.DoStuff());

或者,编写自己的ForEach扩展方法:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}