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

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

真正的语法是什么?


当前回答

为了保持流利,可以使用以下技巧:

GetItems()
    .Select(i => new Action(i.DoStuf)))
    .Aggregate((a, b) => a + b)
    .Invoke();

其他回答

现在我们可以选择。。。

        ParallelOptions parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = 4;
#if DEBUG
        parallelOptions.MaxDegreeOfParallelism = 1;
#endif
        Parallel.ForEach(bookIdList, parallelOptions, bookID => UpdateStockCount(bookID));

当然,这打开了一个全新的线虫罐头。

ps(对不起,字体是系统决定的)

让你的副作用远离我的IEnumerable

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

正如其他人在国内外指出的,LINQ和IEnumerable方法预计不会产生副作用。

你真的想对IEnumerable中的每个项目“做点什么”吗?那么foreach是最好的选择。当这里出现副作用时,人们并不感到惊讶。

foreach (var i in items) i.DoStuff();

我打赌你不想有副作用

然而,根据我的经验,通常不需要副作用。通常情况下,有一个简单的LINQ查询等待被发现,并伴随着Jon Skeet、Eric Lippert或Marc Gravell的StackOverflow.com回答,解释如何做您想要的事情!

一些示例

如果您实际上只是在聚合(累积)一些值,那么应该考虑聚合扩展方法。

items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));

也许您想从现有值创建一个新的IEnumerable。

items.Select(x => Transform(x));

或者你想创建一个查找表:

items.ToLookup(x, x => GetTheKey(x))

可能性的列表(双关语并非完全有意)还在继续。

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

又一个ForEach示例

public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
    var workingAddresses = new List<AddressEntry>();

    addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));

    return workingAddresses;
}

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()都保存在库中。